production_models 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 58a6836d7a856be664ab2523a95af7cda236e2ce
4
+ data.tar.gz: 0c6d3d0741d50c43e0fa62a79b181476d2ae2611
5
+ SHA512:
6
+ metadata.gz: c79e913e4a536e44ee1c5e0e6155b8812f2702f5cb49904a1a2e3709d5dc31aaa1ad2f4e5397fca5fb680213419f41d36dac7eb410b68c64a4634e246506a292
7
+ data.tar.gz: 640ff84f9692873e86f0e9a9ed81b66ac79f03bee60afa0aaa3f1b5147a20ccbf9a7c19bdf864710eca046f24a0fac6a6192ec45a847053dcdd3ec046a1ede5b
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in production_models.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,36 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ production_models (0.0.1)
5
+ activerecord (~> 3.2)
6
+ database_cleaner (~> 1.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activemodel (3.2.14)
12
+ activesupport (= 3.2.14)
13
+ builder (~> 3.0.0)
14
+ activerecord (3.2.14)
15
+ activemodel (= 3.2.14)
16
+ activesupport (= 3.2.14)
17
+ arel (~> 3.0.2)
18
+ tzinfo (~> 0.3.29)
19
+ activesupport (3.2.14)
20
+ i18n (~> 0.6, >= 0.6.4)
21
+ multi_json (~> 1.0)
22
+ arel (3.0.2)
23
+ builder (3.0.4)
24
+ database_cleaner (1.0.1)
25
+ i18n (0.6.4)
26
+ multi_json (1.7.7)
27
+ rake (10.1.0)
28
+ tzinfo (0.3.37)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ bundler (~> 1.3)
35
+ production_models!
36
+ rake
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Luciano Di Lucrezia
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # ProductionModels
2
+
3
+ Easily access your data in the production database from the console.
4
+
5
+ Ever wanted to take a peek in the production data while developing, or to
6
+ transfer data from one database to the other? With ProductionModels, you can
7
+ use the same classes to access both databases simultaneously.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'production_models'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install production_models
22
+
23
+ Once loaded, remember to load the class with:
24
+
25
+ require 'production'
26
+
27
+ (that's right, just `production` and not `production_models`)
28
+
29
+ ## Usage
30
+
31
+ There are two forms for accessing your production database:
32
+
33
+ 1. Prepend `Production::` to your model's class and you're accessing the
34
+ production database (quicker but has caveats, see section below)
35
+
36
+ 2. Use `Production.wrap(ModelClass)` to call `ModelClass` methods on the
37
+ production database (slower to type and execute, but safer)
38
+
39
+ You can specify any other connection defined in `config/database.yml` by
40
+ calling `Production.connection = :connection_name` or by passing a database
41
+ URI, just as you would with `ActiveRecord::Base.establish_connection` because,
42
+ well, that's what happens behind the scenes. By default, you're accessing the
43
+ database configured in the `production` section of the configuration file.
44
+
45
+ In addition you can sync tables between environments with
46
+
47
+ Production.push_from_development(ModelClass, AnotherModelClass, YetAnotherModelClass)
48
+
49
+ and similarly with
50
+
51
+ Production.pull_to_development(ModelClass, AnotherModelClass, YetAnotherModelClass)
52
+
53
+ **The destination tables will be truncated**, so please be super-duper careful
54
+ when you use these.
55
+
56
+
57
+ ## Bugs / caveats
58
+
59
+ The namespace approach does some metaprogramming magic to do its dirty job,
60
+ which works fine if your models are in the main namespace (i.e. they live in
61
+ `app/models`), but can lead to unpredictable results if your models are
62
+ namespaced. In particular, if you have a situation where you have
63
+
64
+ class SomeClass < ActiveRecord::Base
65
+ class SomeOtherClass < ActiveRecord::Base
66
+ end
67
+ end
68
+
69
+ then `Production::SomeClass::SomeOtherClass` will **not** point to the
70
+ production database, but instead to the _development_ database! This happens
71
+ because Ruby resolves namespaces from left to right and I couldn't figure out a
72
+ way to trigger a `const_missing` on a constant that's actually there. In this
73
+ case, you'll have to use `Production.wrap(SomeClass::SomeOtherClass)` and
74
+ you'll get a class that will point to the right database.
75
+
76
+ If you have a solution for this, feel free to patch it on. ;-)
77
+
78
+ ## Contributing
79
+
80
+ 1. Fork it
81
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
82
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
83
+ 4. Push to the branch (`git push origin my-new-feature`)
84
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,3 @@
1
+ class Production
2
+ VERSION = "0.0.1"
3
+ end
data/lib/production.rb ADDED
@@ -0,0 +1,71 @@
1
+ require 'production/version'
2
+ require 'database_cleaner'
3
+
4
+ class Production
5
+
6
+ module ClassMethods
7
+ def const_missing(name)
8
+ namespace = self.name.split('::').tap(&:shift).join('::') # remove 'Production' from requested class namespace
9
+ "#{namespace}::#{name}".constantize rescue nil # fire autoload
10
+ if "#{namespace}".constantize.const_defined?(name)
11
+ case "#{namespace}::#{name}".constantize.class.to_s
12
+ when 'Module'
13
+ return Module.new.tap do |m|
14
+ m.extend(ClassMethods)
15
+ const_set(name, m)
16
+ end
17
+ when 'Class'
18
+ klass = Class.new("#{namespace}::#{name}".constantize)
19
+ klass.establish_connection(connection)
20
+ return klass
21
+ end
22
+ end
23
+ super
24
+ end
25
+ end
26
+
27
+ self.extend(ClassMethods)
28
+
29
+ def self.connection
30
+ @connection || :production
31
+ end
32
+
33
+ def self.connection=(conn)
34
+ @connection = conn
35
+ end
36
+
37
+ def self.wrap(klass)
38
+ Class.new(klass).tap { |c| c.establish_connection(connection) }
39
+ end
40
+
41
+ def self.push_from_development(*classes)
42
+ classes.flatten.each do |klass|
43
+ prod_klass = wrap(klass)
44
+ cleaner = DatabaseCleaner::Base.new(:active_record, connection: prod_klass)
45
+ cleaner.clean_with(:truncation, only: [ prod_klass.table_name ])
46
+ prod_klass.transaction do
47
+ klass.find_each do |i|
48
+ prod_klass.new.tap do |j|
49
+ j.assign_attributes(i.attributes, without_protection: true)
50
+ end.save!
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ def self.pull_to_development(*classes)
57
+ classes.flatten.each do |klass|
58
+ prod_klass = wrap(klass)
59
+ cleaner = DatabaseCleaner::Base.new(:active_record, connection: klass)
60
+ cleaner.clean_with(:truncation, only: [ klass.table_name ])
61
+ klass.transaction do
62
+ prod_klass.find_each do |i|
63
+ klass.new.tap do |j|
64
+ j.assign_attributes(i.attributes, without_protection: true)
65
+ end.save!
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ end
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'production/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "production_models"
8
+ spec.version = Production::VERSION
9
+ spec.authors = ["Luciano Di Lucrezia"]
10
+ spec.email = ["luciano.dilucrezia@gmail.com"]
11
+ spec.description = %q{Access your production models in development environment.}
12
+ spec.summary = %q{Wraps production ActiveRecord models in a new namespace for easy access and transfer from development environment.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_runtime_dependency "database_cleaner", "~> 1.0"
24
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: production_models
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Luciano Di Lucrezia
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-07-28 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.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: database_cleaner
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ description: Access your production models in development environment.
56
+ email:
57
+ - luciano.dilucrezia@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - Gemfile
64
+ - Gemfile.lock
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - lib/production.rb
69
+ - lib/production/version.rb
70
+ - production_models.gemspec
71
+ homepage: ''
72
+ licenses:
73
+ - MIT
74
+ metadata: {}
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubyforge_project:
91
+ rubygems_version: 2.0.3
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: Wraps production ActiveRecord models in a new namespace for easy access and
95
+ transfer from development environment.
96
+ test_files: []