augmentor 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/MIT-LICENSE +20 -0
- data/README.md +62 -0
- data/Rakefile +22 -0
- data/augmentor.gemspec +30 -0
- data/lib/augmentor.rb +91 -0
- data/lib/augmentor/version.rb +17 -0
- data/lib/generators/augmentor/augment_generator.rb +24 -0
- data/lib/generators/augmentor/templates/augment_migration.rb +7 -0
- data/test/augmentor_test.rb +83 -0
- data/test/test_helper.rb +41 -0
- metadata +91 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3338e4fc05b991fc6efe290d597900bfc9255b7b
|
4
|
+
data.tar.gz: c86b54664ac2efd2948cc6c0871b43385cddad5e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 97e003096833906a362dc0adb295b48bab2c85bcb4354b6c91b3fc72260581ff82c9bfaeaa666c0f16897f5b488450911eb84b28faecff73288e3abbf0eb4d02
|
7
|
+
data.tar.gz: 36112dfbaca7c47441639ce3d8c4f7c6f5a9450996633fc71b4238862d5c42f31454d8012aac52270d94f4d7c048853d12fb4d02c0dc5d814be3a5c5c5ba173f
|
data/.gitignore
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 chaunce - chaunce.slc@gmail.com
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# augmentor
|
2
|
+
|
3
|
+
Augment an ActiveRecord class by including additional ActiveRecord classes
|
4
|
+
|
5
|
+
The Augmentor gem allows an ActiveRecord class to inherit all attributes and methods from one or more other ActiveRecord classes, including those provided by ActiveRecord such as getters and setters, as local.
|
6
|
+
|
7
|
+
This allows you to effectively span the data stored for an ActiveRecord class across multiple table without using ActiveRecord relations to get or set the data. To ensure best performance, data
|
8
|
+
|
9
|
+
## Dependencies
|
10
|
+
|
11
|
+
the following gems are required
|
12
|
+
|
13
|
+
gem 'rails', '>= 3.2'
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
install manually
|
18
|
+
|
19
|
+
gem install augmentor
|
20
|
+
|
21
|
+
or add it to your Gemfile
|
22
|
+
|
23
|
+
gem 'augmentor'
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
### Update Database
|
28
|
+
|
29
|
+
#### create migration to add augmentor associations field to an existing class
|
30
|
+
|
31
|
+
rails generate augmentor:augment user person
|
32
|
+
rake db:migrate
|
33
|
+
|
34
|
+
#### or create migration to add augmentor associations field to a new class
|
35
|
+
|
36
|
+
rails generate model person first_name:string, last_name:string, user:augment
|
37
|
+
rake db:migrate
|
38
|
+
|
39
|
+
### Update Models
|
40
|
+
|
41
|
+
#### include in the augmented class
|
42
|
+
|
43
|
+
class User < ActiveRecord::Base
|
44
|
+
augmented_by :person
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
#### include in the augmenting class
|
49
|
+
|
50
|
+
class Person < ActiveRecord::Base
|
51
|
+
augment :user
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
##### Notes
|
56
|
+
|
57
|
+
augmentor associations accepts many ActiveRecord association options, but will only associate one level deep and can not use :through
|
58
|
+
|
59
|
+
class User < ActiveRecord::Base
|
60
|
+
augmented_by :individual, class_name: :person, inverse_of: :user
|
61
|
+
|
62
|
+
end
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rdoc/task'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the augmentor gem.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Generate documentation for the augmentor gem.'
|
16
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'augmentor'
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
20
|
+
rdoc.rdoc_files.include('README*')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
data/augmentor.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
lib = File.expand_path('../lib/', __FILE__)
|
2
|
+
$:.unshift lib unless $:.include?(lib)
|
3
|
+
|
4
|
+
require 'augmentor/version'
|
5
|
+
require 'date'
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = 'augmentor'
|
9
|
+
s.version = Augmentor::Version.string
|
10
|
+
s.date = Date.today
|
11
|
+
|
12
|
+
s.summary = 'Augment an ActiveRecord class by including additional extension classes'
|
13
|
+
s.description = 'Augment an ActiveRecord class by including one or moe additional ActiveRecord extension classes. The augmented class will inherit all attributes and methods, including those provided by ActiveRecord such as getters and setters, as local.'
|
14
|
+
s.license = 'MIT'
|
15
|
+
|
16
|
+
s.author = 'chaunce'
|
17
|
+
s.email = 'chaunce.slc@gmail.com'
|
18
|
+
s.homepage = 'http://github.com/chaunce/augmentor'
|
19
|
+
|
20
|
+
s.has_rdoc = false
|
21
|
+
s.rdoc_options = ['--line-numbers', '--inline-source', '--main', 'README.rdoc']
|
22
|
+
|
23
|
+
s.require_paths = ['lib']
|
24
|
+
|
25
|
+
s.files = `git ls-files`.split("\n")
|
26
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
27
|
+
|
28
|
+
s.add_dependency('rails', ['>= 3.2'])
|
29
|
+
s.add_development_dependency('sqlite3')
|
30
|
+
end
|
data/lib/augmentor.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
module Augmentor
|
5
|
+
autoload :Version, 'augmentor/version'
|
6
|
+
|
7
|
+
module ActiveRecord
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def augment(*args)
|
12
|
+
validate_augmentor_args(args)
|
13
|
+
klass, options, klass_name = parse_augmentor_args(args)
|
14
|
+
belongs_to klass, options
|
15
|
+
validates_presence_of :"#{klass}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def augmented_by(*args)
|
19
|
+
validate_augmentor_args(args)
|
20
|
+
klass, options, klass_name = parse_augmentor_args(args)
|
21
|
+
has_one klass, {dependent: :destroy, inverse_of: :"#{self.name.underscore}"}.merge(options)
|
22
|
+
define_method "#{klass}_must_be_valid" do
|
23
|
+
if self.send(klass).valid?
|
24
|
+
true
|
25
|
+
else
|
26
|
+
self.errors.messages.merge!(self.send(klass).errors.messages)
|
27
|
+
false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
validate :"#{klass}_must_be_valid"
|
31
|
+
|
32
|
+
define_method "#{klass}_with_autobuild" do
|
33
|
+
self.send(:"#{klass}_without_autobuild") || self.send(:"build_#{klass}")
|
34
|
+
end
|
35
|
+
alias_method_chain :"#{klass}", :autobuild
|
36
|
+
|
37
|
+
after_initialize do
|
38
|
+
all_attributes = klass_name.constantize.content_columns.map(&:name)
|
39
|
+
attributes_to_delegate = all_attributes - self.class.content_columns.map(&:name)
|
40
|
+
attributes_to_delegate.each do |attrib|
|
41
|
+
class_eval <<-RUBY
|
42
|
+
def #{attrib}
|
43
|
+
#{klass}.#{attrib}
|
44
|
+
end
|
45
|
+
def #{attrib}=(value)
|
46
|
+
self.#{klass}.#{attrib} = value
|
47
|
+
end
|
48
|
+
def #{attrib}?
|
49
|
+
self.#{klass}.#{attrib}?
|
50
|
+
end
|
51
|
+
RUBY
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def validate_augmentor_args(args)
|
59
|
+
raise ArgumentError, "wrong number of arguments (#{args.length} for 1+)" unless args.length >= 1
|
60
|
+
end
|
61
|
+
def parse_augmentor_args(args)
|
62
|
+
parse_args = args.dup
|
63
|
+
options = args.extract_options!
|
64
|
+
klass = args.first
|
65
|
+
klass_name = options[:class_name] || klass.to_s.classify
|
66
|
+
return klass, options, klass_name
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
module SchemaDefinitions
|
73
|
+
module AugmentMethod
|
74
|
+
def augment(*args)
|
75
|
+
options = (args.extract_options!).merge({index:true})
|
76
|
+
args.each do |col|
|
77
|
+
column("#{col}_id", :integer, options)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
def self.load!
|
82
|
+
::ActiveRecord::ConnectionAdapters::TableDefinition.class_eval { include Augmentor::SchemaDefinitions::AugmentMethod }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
ActiveSupport.on_load :active_record do
|
89
|
+
Augmentor::SchemaDefinitions.load!
|
90
|
+
ActiveRecord::Base.send(:include, Augmentor::ActiveRecord)
|
91
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Augmentor
|
2
|
+
# Contains information about this gem's version
|
3
|
+
module Version
|
4
|
+
MAJOR = 0
|
5
|
+
MINOR = 0
|
6
|
+
PATCH = 1
|
7
|
+
|
8
|
+
# Returns a version string by joining <tt>MAJOR</tt>, <tt>MINOR</tt>, and <tt>PATCH</tt> with <tt>'.'</tt>
|
9
|
+
#
|
10
|
+
# Example
|
11
|
+
#
|
12
|
+
# Version.string # '1.0.2'
|
13
|
+
def self.string
|
14
|
+
[MAJOR, MINOR, PATCH].join('.')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
require 'rails/generators/active_record'
|
4
|
+
|
5
|
+
module Augmentor
|
6
|
+
module Generators
|
7
|
+
class AugmentGenerator < ::Rails::Generators::Base
|
8
|
+
include Rails::Generators::Migration
|
9
|
+
source_root File.expand_path('../templates', __FILE__)
|
10
|
+
|
11
|
+
argument :augmented_class, :type => :string
|
12
|
+
argument :extension_class, :type => :string
|
13
|
+
|
14
|
+
def self.next_migration_number(path)
|
15
|
+
ActiveRecord::Generators::Base.next_migration_number(path)
|
16
|
+
end
|
17
|
+
|
18
|
+
def copy_migration
|
19
|
+
migration_template 'augment_migration.rb', "db/migrate/add_#{extension_class.underscore.singularize}_as_augmentor_to_#{augmented_class.underscore.singularize}.rb"
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class Add<%= extension_class.camelize.singularize %>AsAugmentorTo<%= augmented_class.camelize.singularize %> < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
change_table :<%= extension_class.underscore.pluralize %> do |t|
|
4
|
+
t.augment :<%= augmented_class.underscore.singularize %>, index: true
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
|
3
|
+
class AugmentorTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@name = 'John Doe'
|
6
|
+
@password = 'p@$$w0rd'
|
7
|
+
@login = 'john'
|
8
|
+
@user_count = User.count
|
9
|
+
@person_count = Person.count
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_associations_are_implemented
|
13
|
+
user = User.new
|
14
|
+
assert user.person.present?
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_can_set_save_and_get_augmentor_attributes
|
18
|
+
user = User.new
|
19
|
+
user.name = @name
|
20
|
+
user.login = @login
|
21
|
+
user.password = @password
|
22
|
+
user.save!
|
23
|
+
user = User.find(user.id)
|
24
|
+
assert_equal @name, user.name
|
25
|
+
assert_equal @login, user.login
|
26
|
+
assert_equal @password, user.password
|
27
|
+
assert_equal @user_count+1, User.count
|
28
|
+
assert_equal @person_count+1, Person.count
|
29
|
+
assert_equal @name, Person.last.attributes['name']
|
30
|
+
assert_equal @login, User.last.attributes['login']
|
31
|
+
assert_equal @password, User.last.attributes['password']
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_destroy_augmented_will_destroy_augmentor
|
35
|
+
user = User.new
|
36
|
+
user.name = @name
|
37
|
+
user.login = @login
|
38
|
+
user.password = @password
|
39
|
+
user.save
|
40
|
+
assert_equal @user_count+1, User.count
|
41
|
+
assert_equal @person_count+1, Person.count
|
42
|
+
user_id = user.id
|
43
|
+
person_id = user.person.id
|
44
|
+
user.destroy
|
45
|
+
assert_equal @user_count, User.count
|
46
|
+
assert_equal @person_count, Person.count
|
47
|
+
assert !User.exists?(user_id)
|
48
|
+
assert !Person.exists?(person_id)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_inherits_augmentor_methods
|
52
|
+
person_jim = Person.new
|
53
|
+
person_jim.name = 'jim'
|
54
|
+
assert person_jim.is_jim?
|
55
|
+
person_jim.name = 'bob'
|
56
|
+
assert !person_jim.is_jim?
|
57
|
+
|
58
|
+
user_jim = User.new
|
59
|
+
assert user_jim.respond_to? :is_jim?
|
60
|
+
user_jim.name = 'jim'
|
61
|
+
assert user_jim.is_jim?
|
62
|
+
user_jim.name = 'bob'
|
63
|
+
assert !user_jim.is_jim?
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_may_override_augmentor_methods
|
67
|
+
person_bob = Person.new
|
68
|
+
person_bob.name = 'bob'
|
69
|
+
assert person_bob.is_bob?
|
70
|
+
person_bob.name = 'robert'
|
71
|
+
assert !person_bob.is_bob?
|
72
|
+
|
73
|
+
user_bob = User.new
|
74
|
+
assert user_bob.respond_to? :is_bob?
|
75
|
+
user_bob.name = 'bob'
|
76
|
+
assert user_bob.is_bob?
|
77
|
+
user_bob.name = 'robert'
|
78
|
+
assert user_bob.is_bob?
|
79
|
+
user_bob.name = 'jim'
|
80
|
+
assert !user_bob.is_bob?
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$:.unshift(File.dirname(__FILE__))
|
3
|
+
require 'augmentor'
|
4
|
+
|
5
|
+
require 'active_record'
|
6
|
+
require 'sqlite3'
|
7
|
+
require 'test/unit'
|
8
|
+
require 'debugger'
|
9
|
+
|
10
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
11
|
+
|
12
|
+
ActiveRecord::Schema.define(:version => 1) do
|
13
|
+
create_table :people do |t|
|
14
|
+
t.string :name
|
15
|
+
t.augment :user
|
16
|
+
end
|
17
|
+
create_table :users do |t|
|
18
|
+
t.string :login
|
19
|
+
t.string :password
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Person < ActiveRecord::Base
|
24
|
+
augment :user
|
25
|
+
|
26
|
+
def is_bob?
|
27
|
+
self.name == 'bob'
|
28
|
+
end
|
29
|
+
|
30
|
+
def is_jim?
|
31
|
+
self.name == 'jim'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class User < ActiveRecord::Base
|
36
|
+
augmented_by :person
|
37
|
+
|
38
|
+
def is_bob?
|
39
|
+
['robert', 'rob', 'bob'].include?(self.name)
|
40
|
+
end
|
41
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: augmentor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- chaunce
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sqlite3
|
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
|
+
description: Augment an ActiveRecord class by including one or moe additional ActiveRecord
|
42
|
+
extension classes. The augmented class will inherit all attributes and methods,
|
43
|
+
including those provided by ActiveRecord such as getters and setters, as local.
|
44
|
+
email: chaunce.slc@gmail.com
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- .gitignore
|
50
|
+
- MIT-LICENSE
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- augmentor.gemspec
|
54
|
+
- lib/augmentor.rb
|
55
|
+
- lib/augmentor/version.rb
|
56
|
+
- lib/generators/augmentor/augment_generator.rb
|
57
|
+
- lib/generators/augmentor/templates/augment_migration.rb
|
58
|
+
- test/augmentor_test.rb
|
59
|
+
- test/test_helper.rb
|
60
|
+
homepage: http://github.com/chaunce/augmentor
|
61
|
+
licenses:
|
62
|
+
- MIT
|
63
|
+
metadata: {}
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options:
|
66
|
+
- --line-numbers
|
67
|
+
- --inline-source
|
68
|
+
- --main
|
69
|
+
- README.rdoc
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
requirements: []
|
83
|
+
rubyforge_project:
|
84
|
+
rubygems_version: 2.3.0
|
85
|
+
signing_key:
|
86
|
+
specification_version: 4
|
87
|
+
summary: Augment an ActiveRecord class by including additional extension classes
|
88
|
+
test_files:
|
89
|
+
- test/augmentor_test.rb
|
90
|
+
- test/test_helper.rb
|
91
|
+
has_rdoc: false
|