ar-monocle 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3e87742c40793bc87a080779df7810ce565acf4a
4
+ data.tar.gz: f660aa91f8e80cc8da97092da30a0e4e4ca4ac6b
5
+ SHA512:
6
+ metadata.gz: 3a00f377c8500d1f45a2cf0986bb2dff9ca490c20cd244b51209365a97d24eeb940f1dcbd4392383fa754a7cf967ab6f50ef869a11d4e4d5542fd70ef4f0ec3e
7
+ data.tar.gz: 52aaa8db222c5519a4bd47eace5726768db6ff962f0f9f967c2cb9e9f10babbc320f48cb39f59e96025863213fce94e047e554d5624cc0dbbf7319f2206424e9
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in monocle.gemspec
4
+ gemspec
@@ -0,0 +1,75 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ar-monocle (0.1.0)
5
+ activerecord (>= 4, < 6)
6
+ activesupport (>= 4, < 6)
7
+ rake
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ activemodel (5.0.0.1)
13
+ activesupport (= 5.0.0.1)
14
+ activerecord (5.0.0.1)
15
+ activemodel (= 5.0.0.1)
16
+ activesupport (= 5.0.0.1)
17
+ arel (~> 7.0)
18
+ activesupport (5.0.0.1)
19
+ concurrent-ruby (~> 1.0, >= 1.0.2)
20
+ i18n (~> 0.7)
21
+ minitest (~> 5.1)
22
+ tzinfo (~> 1.1)
23
+ arel (7.1.4)
24
+ coderay (1.1.1)
25
+ concurrent-ruby (1.0.5)
26
+ database_cleaner (1.5.3)
27
+ diff-lcs (1.3)
28
+ dotenv (2.2.0)
29
+ i18n (0.7.0)
30
+ metaclass (0.0.4)
31
+ method_source (0.8.2)
32
+ minitest (5.10.1)
33
+ mocha (1.2.1)
34
+ metaclass (~> 0.0.1)
35
+ pg (0.19.0)
36
+ pry (0.10.4)
37
+ coderay (~> 1.1.0)
38
+ method_source (~> 0.8.1)
39
+ slop (~> 3.4)
40
+ pry-nav (0.2.4)
41
+ pry (>= 0.9.10, < 0.11.0)
42
+ rake (12.0.0)
43
+ rspec (3.5.0)
44
+ rspec-core (~> 3.5.0)
45
+ rspec-expectations (~> 3.5.0)
46
+ rspec-mocks (~> 3.5.0)
47
+ rspec-core (3.5.4)
48
+ rspec-support (~> 3.5.0)
49
+ rspec-expectations (3.5.0)
50
+ diff-lcs (>= 1.2.0, < 2.0)
51
+ rspec-support (~> 3.5.0)
52
+ rspec-mocks (3.5.0)
53
+ diff-lcs (>= 1.2.0, < 2.0)
54
+ rspec-support (~> 3.5.0)
55
+ rspec-support (3.5.0)
56
+ slop (3.6.0)
57
+ thread_safe (0.3.6)
58
+ tzinfo (1.2.2)
59
+ thread_safe (~> 0.1)
60
+
61
+ PLATFORMS
62
+ ruby
63
+
64
+ DEPENDENCIES
65
+ ar-monocle!
66
+ bundler (~> 1.14)
67
+ database_cleaner
68
+ dotenv
69
+ mocha
70
+ pg
71
+ pry-nav
72
+ rspec (~> 3.0)
73
+
74
+ BUNDLED WITH
75
+ 1.14.5
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Leonardo Bighetti
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,99 @@
1
+
2
+ # Monocle
3
+
4
+ <img align="right" src="https://lh3.googleusercontent.com/SoJ_7q3soZxT97yNmlBx8eFqs7iXH_azC1H9vXCsglXq5GaR6rXCtf9Xzq42fJTAg7gL=s107"></img>Monocle helps you tame your database views by keeping the SQLs versioned neatly in your project and knowing when and how to migrate them if necessary. It knows how to deal with PostgreSQL materialized views and dependencies (view A points to view B) as well as regular views.
5
+
6
+ Monocle works with or without Rails, all it assumes is you're using ActiveRecord. See _Usage_ for more details.
7
+
8
+ ## Reasoning
9
+
10
+ At [InvitedHome](http://invitedhome.com/) we needed an easy to use system to manage a bunch of complex views (often materialized) that we use for things like caching.
11
+
12
+ The only gem that did something similar at the time was Thoughtbot's [Scenic](https://github.com/thoughtbot/scenic), but we didn't like some of its features such as how it would generate multiple versions of the same view's SQL.
13
+
14
+ We wanted something way simpler, one SQL file per view, versioning maintained by a timestamp at the top of the file. Thus, Monocle was born.
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ ```ruby
21
+ gem 'ar-monocle', require: 'monocle'
22
+ ```
23
+
24
+ And then execute:
25
+
26
+ $ bundle
27
+
28
+ Or install it yourself as:
29
+
30
+ $ gem install ar-monocle
31
+
32
+ ## Setup
33
+
34
+ If you're using Rails, there are generators for bootstrapping the gem:
35
+
36
+ $ rails g monocle:install
37
+
38
+ It will generate a migration for creating the Monocle::Migration table. If you're not using Rails, you'll need to create the table yourself. Check https://github.com/darkside/monocle/blob/master/spec/support/database_utils.rb for an example on how to do it.
39
+
40
+ ## Usage
41
+
42
+ The basic gist is you have a `db/views` in your project which contains all the view / materialized view SQL definitions. On top of those files there's a timestamp that you can control. Every time you change that timestamp, Monocle will try to migrate that view when calling `rake monocle:migrate`. You can automate this easily by hooking `monocle:migrate` to your deployment process.
43
+
44
+ Monocle knows about view dependencies and will drop and recreate dependants as necessary. So if you have a view A that references a view B and you need to upgrade view B, it will drop view A first, then drop and create view B, then create view A.
45
+
46
+ ## Included Generators (for Rails)
47
+
48
+ ### Generating a view
49
+
50
+ With Rails, you can use the generator:
51
+
52
+ $ rails g monocle:view view_name
53
+
54
+ This will generate a Monocle SQL template and a model. You can skip creating the model with `--skip-model`.
55
+
56
+ ### Generating a materialized view
57
+
58
+ With Rails, you can use the generator:
59
+
60
+ $ rails g monocle:matview view_name
61
+
62
+ This will generate a Monocle materialized SQL template and a model. You can skip creating the model with `--skip-model`.
63
+
64
+ ## Included Rake Tasks
65
+
66
+ ### List all views
67
+
68
+ You can use `rake monocle:list` to see all the view names that are being managed by Monocle.
69
+
70
+ ### List all migrated view slugs
71
+
72
+ You can use `rake monocle:versions` to see all the view slugs that have been migrated by Monocle.
73
+
74
+ ### Migrate views
75
+
76
+ You can use `rake monocle:migrate` to migrate any views that have a new timestamp. I recommend you hook this to your deployment process i.e after you call `rake db:migrate`
77
+
78
+ ### Bumping a view timestamp
79
+
80
+ With monocle, you decide when it's time to upgrade a view. So even if you have an updated view definition that you're working on, it won't actually change it unless the timestamp has changed. To bump a view timestamp, you can either do it yourself by changing the first line of the template or use the supplied rake task:
81
+
82
+ $ rake monocle:bump[my_view_name]
83
+
84
+ It will automatically bump that view's timestamp to the current time.
85
+
86
+ ## Development
87
+
88
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
89
+
90
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
91
+
92
+ ## Contributing
93
+
94
+ Bug reports and pull requests are welcome on GitHub at https://github.com/darkside/monocle.
95
+
96
+ ## License
97
+
98
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
99
+
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ Dir.glob('lib/tasks/*.rake').each {|r| import r}
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "monocle"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,83 @@
1
+ # Bare essentials from Rails to make this work neatly
2
+ require "active_support/core_ext/module/delegation"
3
+ require 'active_record'
4
+
5
+ require 'monocle/railtie' if defined?(Rails)
6
+
7
+ require "monocle/version"
8
+ require "monocle/version_generator"
9
+ require "monocle/view"
10
+ require "monocle/migration"
11
+
12
+ require "monocle/bump_command"
13
+ require "monocle/list_command"
14
+
15
+ module Monocle
16
+ def self.list
17
+ @list ||= ListCommand.new.call
18
+ end
19
+
20
+ def self.drop(view_name)
21
+ fetch(view_name).drop
22
+ end
23
+
24
+ def self.create(view_name)
25
+ fetch(view_name).create
26
+ end
27
+
28
+ def self.versions
29
+ Migration.versions
30
+ end
31
+
32
+ def self.migrate
33
+ logger.info "Starting materialized views migrations..."
34
+ list.each do |key, view|
35
+ logger.debug "Checking if #{key} is up to date..."
36
+ view.migrate
37
+ end
38
+ logger.info "All done!"
39
+ end
40
+
41
+ def self.bump(view_name)
42
+ BumpCommand.new(fetch(view_name)).call
43
+ end
44
+
45
+ def self.refresh(view_name, concurrently: false)
46
+ fetch(view_name).refresh concurrently: concurrently
47
+ end
48
+
49
+ def self.logger
50
+ # FIXME: This will need to be configurable
51
+ @logger ||= if defined?(Rails)
52
+ Rails.logger
53
+ else
54
+ Logger.new(STDOUT).tap do |logger|
55
+ logger.level = Logger::ERROR
56
+ end
57
+ end
58
+ end
59
+
60
+ def self.views_path
61
+ # FIXME: This will need to be configurable
62
+ @views_path ||= if defined?(Rails)
63
+ File.join Rails.root, "db/views"
64
+ else
65
+ File.join Monocle.root, "db/views"
66
+ end
67
+ end
68
+
69
+ def self.root
70
+ File.expand_path(File.dirname(__dir__))
71
+ end
72
+
73
+ protected
74
+
75
+ def self.fetch(view_name)
76
+ view_name = symbolize_name(view_name)
77
+ list.fetch(view_name)
78
+ end
79
+
80
+ def self.symbolize_name(name)
81
+ name.is_a?(String) ? name.to_sym : name
82
+ end
83
+ end
@@ -0,0 +1,23 @@
1
+ class Monocle::BumpCommand
2
+
3
+ attr_reader :view
4
+
5
+ def initialize(view)
6
+ @view = view
7
+ end
8
+
9
+ def call
10
+ # Get the SQL from the file, skipping the timestamp row
11
+ # Drop the newlines too
12
+ sql = File.readlines(view.path_for_sql)[1..-1]
13
+ # Generate the new timestamp line
14
+ timestamp = ["-- Timestamp: #{Time.now}\n"]
15
+ # Put it back together
16
+ new_sql = (timestamp + sql).join
17
+ # Open the file for writing (no w+, we want to clear it up)
18
+ File.open(view.path_for_sql, "w") do |f|
19
+ f << new_sql
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,10 @@
1
+ require 'rails/generators'
2
+
3
+ module Monocle::Generators
4
+ class InstallGenerator < Rails::Generators::Base
5
+ desc "Creates everything you need to start rolling with monocle"
6
+ def create_migration
7
+ invoke "migration", ["CreateMonocleMigrations", "version:string:uniq", "--primary-key-type=false"], options
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,27 @@
1
+ require "rails/generators"
2
+
3
+ module Monocle::Generators
4
+ class MatviewGenerator < Rails::Generators::NamedBase
5
+ desc "Creates a materialized view SQL template and optionally a model to go with it"
6
+ class_option :skip_model, type: :boolean, default: false, desc: "Skips model generation"
7
+
8
+ def generate_sql_file
9
+ create_file "db/views/#{file_name}.sql" do
10
+ <<-EOF
11
+ -- Timestamp: #{Time.now}
12
+ CREATE MATERIALIZED VIEW #{file_name} AS
13
+ -- Add your stuff here
14
+ ;
15
+ EOF
16
+ end
17
+ end
18
+
19
+ def generate_model_file
20
+ # Don't do anything if we're skipping this
21
+ return if options[:skip_model]
22
+ # Invoke rails' nifty model generator for us
23
+ invoke "model", [file_path.singularize], options.merge(migration: false, test_framework: false)
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ require "rails/generators"
2
+
3
+ module Monocle::Generators
4
+ class ViewGenerator < Rails::Generators::NamedBase
5
+ desc "Creates a view SQL template and optionally a model to go with it"
6
+ class_option :skip_model, type: :boolean, default: false, desc: "Skips model generation"
7
+
8
+ def generate_sql_file
9
+ create_file "db/views/#{file_name}.sql" do
10
+ <<-EOF
11
+ -- Timestamp: #{Time.now}
12
+ CREATE OR REPLACE VIEW #{file_name} AS
13
+ -- Add your stuff here
14
+ ;
15
+ EOF
16
+ end
17
+ end
18
+
19
+ def generate_model_file
20
+ # Don't do anything if we're skipping this
21
+ return if options[:skip_model]
22
+ # Invoke rails' nifty model generator for us
23
+ invoke "model", [file_path.singularize], options.merge(migration: false, test_framework: false)
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ module Monocle
2
+ class ListCommand
3
+ delegate :views_path, to: Monocle
4
+
5
+ attr_reader :view_names
6
+
7
+ def initialize
8
+ @view_names = Dir[File.join(views_path, "*.sql")].map { |f| File.basename(f, ".sql") }
9
+ end
10
+
11
+ def call
12
+ {}.tap do |hash|
13
+ view_names.each do |view_name|
14
+ hash[view_name.to_sym] = View.new(view_name)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,8 @@
1
+ module Monocle
2
+ class Migration < ActiveRecord::Base
3
+ self.table_name = 'monocle_migrations'
4
+ def self.versions
5
+ all.pluck(:version)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module Monocle
2
+ class Railtie < Rails::Railtie
3
+ rake_tasks do
4
+ load File.join(Monocle.root, "lib/tasks/monocle.rake")
5
+ end
6
+
7
+ generators do
8
+ Dir[File.join(Monocle.root, "lib/monocle/generators/*.rb")].each { |f| require f }
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module Monocle
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1,18 @@
1
+ module Monocle
2
+ class VersionGenerator
3
+ attr_reader :path, :view
4
+
5
+ def initialize(path)
6
+ @path = path
7
+ @view = File.basename(path, ".sql")
8
+ end
9
+
10
+ def generate
11
+ timestamp = File.open path, &:readline
12
+ fail "can't read timestamp of #{path}! Aborting..." unless timestamp.starts_with? "-- Timestamp: "
13
+ # Get only the digits out of the timestamp line
14
+ timestamp.gsub!(/[^\d]/, '')
15
+ "#{view}_#{timestamp}"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,92 @@
1
+ # An in-memory representation of the view
2
+ module Monocle
3
+ class View
4
+ attr_reader :name
5
+ attr_accessor :dependants
6
+
7
+ delegate :views_path, :list, :versions, :logger, to: Monocle
8
+ delegate :info, :warn, :error, :debug, to: :logger
9
+
10
+ def initialize(name)
11
+ @name = name
12
+ @dependants = []
13
+ end
14
+
15
+ def materialized?
16
+ !!(@materialized ||= create_command =~ /MATERIALIZED VIEW/i)
17
+ end
18
+
19
+ def drop
20
+ debug "Dropping #{name}..."
21
+ execute drop_command
22
+ true
23
+ rescue ActiveRecord::StatementInvalid => e
24
+ # We have dependants, can't drop this directly.
25
+ if e.message =~ /PG::DependentObjectsStillExist/
26
+ # Find the views in the main list, drop them
27
+ self.dependants = get_dependants_from_error e
28
+ debug "Can't drop #{name}, it has dependants: #{dependants.map(&:name).join(', ')}"
29
+ dependants.each &:drop
30
+ # And try this again
31
+ retry
32
+ else
33
+ fail e
34
+ end
35
+ end
36
+
37
+ def create
38
+ debug "Creating #{name}..."
39
+ execute create_command
40
+ Migration.find_or_create_by version: slug
41
+ dependants.each &:create
42
+ true
43
+ end
44
+
45
+ def migrate
46
+ if versions.include?(slug)
47
+ debug "Skipping #{name} as it's already up to date."
48
+ true
49
+ else
50
+ status = drop && create
51
+ info "#{name} migrated to #{slug}!"
52
+ status
53
+ end
54
+ end
55
+
56
+ def refresh(concurrently: false)
57
+ # We don't refresh normal views
58
+ return false unless materialized?
59
+ _concurrently = "CONCURRENTLY" if concurrently
60
+ execute "REFRESH MATERIALIZED VIEW #{_concurrently} #{name}"
61
+ end
62
+
63
+ def slug
64
+ @slug ||= VersionGenerator.new(path_for_sql).generate
65
+ end
66
+
67
+ def drop_command
68
+ _materialized = 'MATERIALIZED' if materialized?
69
+ "DROP #{_materialized} VIEW IF EXISTS #{name};"
70
+ end
71
+
72
+ def create_command
73
+ @create_command ||= File.read(path_for_sql)
74
+ end
75
+
76
+ def path_for_sql
77
+ @path_for_sql ||= File.join views_path, "#{name}.sql"
78
+ end
79
+
80
+ protected
81
+
82
+ def get_dependants_from_error(e)
83
+ e.message.scan(/(\w+) depends on.+view #{name}/).
84
+ flatten.map { |s| list.fetch s.to_sym }
85
+ end
86
+
87
+ def execute(sql)
88
+ ActiveRecord::Base.connection.execute(sql)
89
+ end
90
+ end
91
+
92
+ end
@@ -0,0 +1,24 @@
1
+ namespace :monocle do
2
+ desc "List all Monocle managed views"
3
+ task :list => :environment do
4
+ Monocle.list
5
+ end
6
+
7
+ desc "List all Monocle view slugs"
8
+ task :versions => :environment do
9
+ Monocle.versions
10
+ end
11
+
12
+ desc "Migrate any monocle views that need migratin'"
13
+ task :migrate => :environment do
14
+ Monocle.migrate
15
+ Rake::Task['db:structure:dump'].invoke
16
+ end
17
+
18
+ desc "Bump a monocle view's timestamp by name"
19
+ task :bump, [:view_name] do |t, args|
20
+ Rake::Task['environment'].invoke
21
+ view_name = args.view_name
22
+ Monocle.bump(view_name)
23
+ end
24
+ end
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'monocle/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ar-monocle"
8
+ spec.version = Monocle::VERSION
9
+ spec.authors = ["Leonardo Bighetti"]
10
+ spec.email = ["leo@invitedhome.com"]
11
+
12
+ spec.summary = %q{Monocle helps you manage your DB views.}
13
+ spec.description = %q{Monocle helps you manage your DB views.}
14
+ spec.homepage = "https://github.com/darkside/monocle"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.14"
25
+ spec.add_development_dependency "rspec", "~> 3.0"
26
+ spec.add_development_dependency "mocha"
27
+ spec.add_development_dependency "pry-nav"
28
+ spec.add_development_dependency "dotenv"
29
+ spec.add_development_dependency "pg"
30
+ spec.add_development_dependency "database_cleaner"
31
+
32
+ spec.add_dependency "rake"
33
+ spec.add_dependency "activesupport", ">= 4", "< 6"
34
+ spec.add_dependency "activerecord", ">= 4", "< 6"
35
+ end
metadata ADDED
@@ -0,0 +1,216 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ar-monocle
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Leonardo Bighetti
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-03-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mocha
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry-nav
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: dotenv
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pg
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: database_cleaner
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: activesupport
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '4'
132
+ - - "<"
133
+ - !ruby/object:Gem::Version
134
+ version: '6'
135
+ type: :runtime
136
+ prerelease: false
137
+ version_requirements: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '4'
142
+ - - "<"
143
+ - !ruby/object:Gem::Version
144
+ version: '6'
145
+ - !ruby/object:Gem::Dependency
146
+ name: activerecord
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '4'
152
+ - - "<"
153
+ - !ruby/object:Gem::Version
154
+ version: '6'
155
+ type: :runtime
156
+ prerelease: false
157
+ version_requirements: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ version: '4'
162
+ - - "<"
163
+ - !ruby/object:Gem::Version
164
+ version: '6'
165
+ description: Monocle helps you manage your DB views.
166
+ email:
167
+ - leo@invitedhome.com
168
+ executables: []
169
+ extensions: []
170
+ extra_rdoc_files: []
171
+ files:
172
+ - Gemfile
173
+ - Gemfile.lock
174
+ - LICENSE.txt
175
+ - README.md
176
+ - Rakefile
177
+ - bin/console
178
+ - bin/setup
179
+ - lib/monocle.rb
180
+ - lib/monocle/bump_command.rb
181
+ - lib/monocle/generators/install_generator.rb
182
+ - lib/monocle/generators/matview_generator.rb
183
+ - lib/monocle/generators/view_generator.rb
184
+ - lib/monocle/list_command.rb
185
+ - lib/monocle/migration.rb
186
+ - lib/monocle/railtie.rb
187
+ - lib/monocle/version.rb
188
+ - lib/monocle/version_generator.rb
189
+ - lib/monocle/view.rb
190
+ - lib/tasks/monocle.rake
191
+ - monocle.gemspec
192
+ homepage: https://github.com/darkside/monocle
193
+ licenses:
194
+ - MIT
195
+ metadata: {}
196
+ post_install_message:
197
+ rdoc_options: []
198
+ require_paths:
199
+ - lib
200
+ required_ruby_version: !ruby/object:Gem::Requirement
201
+ requirements:
202
+ - - ">="
203
+ - !ruby/object:Gem::Version
204
+ version: '0'
205
+ required_rubygems_version: !ruby/object:Gem::Requirement
206
+ requirements:
207
+ - - ">="
208
+ - !ruby/object:Gem::Version
209
+ version: '0'
210
+ requirements: []
211
+ rubyforge_project:
212
+ rubygems_version: 2.5.1
213
+ signing_key:
214
+ specification_version: 4
215
+ summary: Monocle helps you manage your DB views.
216
+ test_files: []