can_be 0.1.0

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.
@@ -0,0 +1,18 @@
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
18
+ log/*.log
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 1.9.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in can_be.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Mark Starkman
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.
@@ -0,0 +1,84 @@
1
+ # CanBe [![Build Status](https://secure.travis-ci.org/mstarkman/can_be.png?branch=master)](https://travis-ci.org/mstarkman/can_be)
2
+
3
+ Adds helper methods to your Active Record models to control the type of record.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'can_be'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install can_be
18
+
19
+ ## Usage
20
+
21
+ Before adding it to your model, you will need to add a database field to
22
+ your model. By default, the `can_be` gem expects your field to be
23
+ called `can_be_type`. However, this can be changed.
24
+
25
+ ```ruby
26
+ class AddCanBeTypeToAddresses < ActiveRecord::Migration
27
+ def change
28
+ add_column :addresses, :can_be_type, :string
29
+ add_index :addresses, :can_be_type
30
+ end
31
+ end
32
+ ```
33
+
34
+ Once you've installed the gem, you will have access to the `can_be` method in your models. The `can_be` method will take a list of types (as symbols) that your model can be represented as.
35
+
36
+ ```ruby
37
+ class Address < ActiveRecord::Base
38
+ can_be :home_address, :work_address, :vacation_address
39
+ end
40
+ ```
41
+
42
+ ### Methods Added to your model
43
+
44
+ The following methods will then be added to your model for each of the types based on the example above.
45
+
46
+ #### Class Methods
47
+
48
+ * `create_home_address` - Creates a new address model in the database with the type of `home_address`
49
+ * `find_by_can_be_types` - Accepts a list of types and returns the results of the database query (note: this is only added once, not for each type)
50
+ * `home_addresses` - Returns a list of the records with a type of `home_address`
51
+ * `new_home_address` - Instantiates a new address model instance with the type of `home_address`
52
+
53
+ #### Instance Methods
54
+
55
+ * `change_to_home_address` - Changes the record to a `home_address` type (does not save it to the database)
56
+ * `change_to_home_address!` - Changes the record to a `home_address` type and saves it to the database
57
+ * `home_address?` - Returns true if the record is a `home_address` type
58
+
59
+ ### Options
60
+
61
+ The following options can be added to the `can_be` method call.
62
+
63
+ * `default_type` - Sets the default value for when a new record is instantiated (it is the first value in the list by default)
64
+ * `field_name` - Sets the ActiveRecord field name that is to be used (by default it expects a `can_be_type` field to be present)
65
+
66
+ Here is an example.
67
+
68
+ ```ruby
69
+ class Person < ActiveRecord::Base
70
+ can_be :male, :female, field_name: :gender, default_type: :female
71
+ end
72
+ ```
73
+
74
+ ## Contributing
75
+
76
+ 1. Fork it
77
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
78
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
79
+ 4. Push to the branch (`git push origin my-new-feature`)
80
+ 5. Create new Pull Request
81
+
82
+ ## License
83
+
84
+ See [LICENSE.txt](https://github.com/mstarkman/can_be/blob/master/LICENSE.txt).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'can_be/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "can_be"
8
+ gem.version = CanBe::VERSION
9
+ gem.authors = ["Mark Starkman"]
10
+ gem.email = ["mrstarkman@gmail.com"]
11
+ gem.description = %q{Adds helper methods to your Active Record models to control the type of record.}
12
+ gem.summary = %q{Adds helper methods to your Active Record models to control the type of record.}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_development_dependency('rspec', '~> 2.0')
21
+ gem.add_development_dependency('sqlite3')
22
+ gem.add_development_dependency('database_cleaner')
23
+ gem.add_development_dependency('rake')
24
+
25
+ gem.add_dependency("activerecord", "~> 3.1")
26
+ gem.add_dependency("activesupport", "~> 3.1")
27
+ end
@@ -0,0 +1,8 @@
1
+ require "can_be/version"
2
+ require "can_be/initializer"
3
+ require "can_be/model_extensions"
4
+ require "can_be/railtie" if defined? Rails
5
+
6
+ module CanBe
7
+ end
8
+
@@ -0,0 +1,90 @@
1
+ module CanBe
2
+ class Initializer
3
+ def initialize(klass, types, options = {})
4
+ @klass = klass
5
+ @types = types
6
+ @options = parse_options(options)
7
+ end
8
+
9
+ def define_methods
10
+ define_instance_methods
11
+ define_class_methods
12
+ define_validations
13
+ end
14
+
15
+ private
16
+ def parse_options(options)
17
+ if options.nil?
18
+ default_options
19
+ else
20
+ default_options.merge(options)
21
+ end
22
+ end
23
+
24
+ def default_options
25
+ {
26
+ field_name: :can_be_type,
27
+ default_type: @types.first
28
+ }
29
+ end
30
+
31
+ def define_instance_methods
32
+ field_name = @options[:field_name]
33
+
34
+ @types.each do |t|
35
+ @klass.instance_eval do
36
+ define_method "#{t}?" do
37
+ send(field_name) == t
38
+ end
39
+
40
+ define_method "change_to_#{t}" do
41
+ send("#{field_name}=", t)
42
+ end
43
+
44
+ define_method "change_to_#{t}!" do
45
+ update_attributes(field_name => t)
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ def define_class_methods
52
+ field_name = @options[:field_name]
53
+ default_type = @options[:default_type]
54
+
55
+ @types.each do |t|
56
+ @klass.class_eval <<-EVAL
57
+ def self.create_#{t}(attributes = {}, options = {}, &block)
58
+ attributes[:#{field_name}] = '#{t}'
59
+ create(attributes, options, &block)
60
+ end
61
+
62
+ def self.new_#{t}(attributes = {}, options = {})
63
+ attributes[:#{field_name}] = '#{t}'
64
+ new(attributes, options)
65
+ end
66
+
67
+ def self.find_by_can_be_types(*types)
68
+ where(#{field_name}: types)
69
+ end
70
+
71
+ def self.#{t.pluralize}
72
+ where(#{field_name}: '#{t}')
73
+ end
74
+
75
+ after_initialize do |model|
76
+ model.#{field_name} = '#{default_type}' if model.#{field_name}.nil?
77
+ end
78
+ EVAL
79
+ end
80
+ end
81
+
82
+ def define_validations
83
+ field_name = @options[:field_name]
84
+
85
+ @klass.class_eval <<-EVAL
86
+ validates_inclusion_of :#{field_name}, in: ['#{@types.join(',').gsub(/,/, "', '")}']
87
+ EVAL
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,18 @@
1
+ require 'active_support/concern'
2
+
3
+ module CanBe
4
+ module ModelExtensions
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def can_be(*types)
9
+ if types.last.is_a?(Hash)
10
+ options = types.last
11
+ types.delete types.last
12
+ end
13
+
14
+ CanBe::Initializer.new(self, types.map(&:to_s), options).define_methods
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ module CanBe
2
+ class Railtie < Rails::Railtie
3
+ initializer 'can_be.model_additions' do
4
+ ActiveSupport.on_load :active_record do
5
+ include CanBe::ModelExtensions
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module CanBe
2
+ VERSION = "0.1.0"
3
+ end
File without changes
@@ -0,0 +1,173 @@
1
+ require 'spec_helper'
2
+
3
+ describe CanBe::ModelExtensions do
4
+ context "instance methods" do
5
+ describe "boolean record methods" do
6
+ it "are created" do
7
+ rec = new_address
8
+ rec.should respond_to :home_address?
9
+ rec.should respond_to :work_address?
10
+ end
11
+
12
+ it "responds true" do
13
+ new_address(:home_address).should be_home_address
14
+ new_address(:work_address).should be_work_address
15
+ end
16
+
17
+ it "responds false" do
18
+ new_address(:work_address).should_not be_home_address
19
+ end
20
+ end
21
+
22
+ describe "change_to methods" do
23
+ it "are created" do
24
+ rec = new_address
25
+ rec.should respond_to :change_to_home_address
26
+ rec.should respond_to :change_to_work_address
27
+ end
28
+
29
+ it "updates the record" do
30
+ rec = new_address(:work_address)
31
+ rec.change_to_home_address
32
+ rec.should be_home_address
33
+ end
34
+
35
+ it "does not update the database" do
36
+ rec = create_address(:work_address)
37
+ rec.change_to_home_address
38
+ Address.first.should_not be_home_address
39
+ end
40
+ end
41
+
42
+ describe "change_to! methods" do
43
+ it "are created" do
44
+ rec = create_address
45
+ rec.should respond_to :change_to_home_address!
46
+ rec.should respond_to :change_to_work_address!
47
+ end
48
+
49
+ it "updates the record" do
50
+ rec = create_address(:work_address)
51
+ rec.change_to_home_address!
52
+ rec.should be_home_address
53
+ end
54
+
55
+ it "updates the database" do
56
+ rec = create_address(:work_address)
57
+ rec.change_to_home_address!
58
+ Address.first.should be_home_address
59
+ end
60
+ end
61
+ end
62
+
63
+ context "class methods" do
64
+ describe "create methods" do
65
+ it "are created" do
66
+ Address.should respond_to :create_home_address
67
+ Address.should respond_to :create_work_address
68
+ end
69
+
70
+ it "create the records in the database" do
71
+ a = Address.create_home_address
72
+ Address.find(a.id).should be_home_address
73
+
74
+ a = Address.create_work_address
75
+ Address.find(a.id).should be_work_address
76
+ end
77
+
78
+ it "creates the records changing to the correct type" do
79
+ a = Address.create_home_address can_be_type: 'work_address'
80
+ Address.find(a.id).should be_home_address
81
+ end
82
+ end
83
+
84
+ describe "new methods" do
85
+ it "are created" do
86
+ Address.should respond_to :new_home_address
87
+ Address.should respond_to :new_work_address
88
+ end
89
+
90
+ it "create the correct type" do
91
+ Address.new_home_address.should be_home_address
92
+ Address.new_work_address.should be_work_address
93
+ end
94
+
95
+ it "create the records changing to the correct type" do
96
+ Address.create_home_address(can_be_type: 'work_address').should be_home_address
97
+ end
98
+
99
+ it "don't create the records in the database" do
100
+ Address.new_home_address
101
+ Address.new_work_address
102
+ Address.count.should == 0
103
+ end
104
+ end
105
+
106
+ describe "finder methods" do
107
+ let(:home_count) { 5 }
108
+ let(:work_count) { 4 }
109
+ let(:vacation_count) { 3 }
110
+
111
+ before :each do
112
+ home_count.times { Address.create_home_address }
113
+ work_count.times { Address.create_work_address }
114
+ vacation_count.times { Address.create_vacation_address }
115
+ end
116
+
117
+ it "are created" do
118
+ Address.should respond_to :find_by_can_be_types
119
+ Address.should respond_to 'home_address'.pluralize
120
+ Address.should respond_to 'work_address'.pluralize
121
+ end
122
+
123
+ it "#find_by_can_be_types returns the correct records" do
124
+ recs = Address.find_by_can_be_types(:home_address, :work_address)
125
+ recs.should have(home_count + work_count).items
126
+ recs.each do |a|
127
+ a.can_be_type.should =~ /^home_address|work_address$/
128
+ end
129
+ end
130
+
131
+ it "returns the correct records" do
132
+ recs = Address.home_addresses
133
+ recs.should have(home_count).items
134
+ recs.each { |a| a.should be_home_address }
135
+
136
+ recs = Address.work_addresses
137
+ recs.should have(work_count).items
138
+ recs.each { |a| a.should be_work_address }
139
+ end
140
+ end
141
+ end
142
+
143
+ context "default type" do
144
+ it "uses the first type as the default" do
145
+ Address.new.should be_home_address
146
+ end
147
+
148
+ it "uses the specified default_type option" do
149
+ Person.new.should be_female
150
+ end
151
+ end
152
+
153
+ context "database field" do
154
+ it "uses the :can_be_type field (default)" do
155
+ Address.new_home_address.can_be_type.should == 'home_address'
156
+ end
157
+
158
+ it "uses the specified field" do
159
+ Person.new_female.gender.should == 'female'
160
+ end
161
+ end
162
+
163
+ context "validity of type value" do
164
+ it "should be valid" do
165
+ Address.new_home_address.should be_valid
166
+ Address.new_work_address.should be_valid
167
+ end
168
+
169
+ it "should not be valid" do
170
+ Address.new(can_be_type: 'invalid type').should_not be_valid
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe CanBe do
4
+ end
@@ -0,0 +1,31 @@
1
+ require 'active_record'
2
+ require 'database_cleaner'
3
+ require 'logger'
4
+ require 'support/model_macros'
5
+
6
+ require 'can_be'
7
+
8
+ ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
9
+ ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), "../log/debug.log"))
10
+ ActiveRecord::Base.send(:include, CanBe::ModelExtensions)
11
+
12
+ # now that we have the database configured, we can create the models and
13
+ # migrate the database
14
+ require 'support/models'
15
+
16
+ RSpec.configure do |config|
17
+ config.include ModelMacros
18
+
19
+ config.before(:suite) do
20
+ DatabaseCleaner.strategy = :transaction
21
+ DatabaseCleaner.clean_with(:truncation)
22
+ end
23
+
24
+ config.before(:each) do
25
+ DatabaseCleaner.start
26
+ end
27
+
28
+ config.after(:each) do
29
+ DatabaseCleaner.clean
30
+ end
31
+ end
@@ -0,0 +1,9 @@
1
+ module ModelMacros
2
+ def new_address(can_be_type = 'home')
3
+ Address.new(can_be_type: can_be_type.to_s)
4
+ end
5
+
6
+ def create_address(can_be_type = 'home')
7
+ Address.create(can_be_type: can_be_type.to_s)
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ require 'active_record'
2
+
3
+ load File.dirname(__FILE__) + '/schema.rb'
4
+
5
+ # The Address model will use the default options
6
+ class Address < ActiveRecord::Base
7
+ can_be :home_address, :work_address, :vacation_address
8
+ end
9
+
10
+ class Person < ActiveRecord::Base
11
+ can_be :male, :female, field_name: :gender, default_type: :female
12
+ end
@@ -0,0 +1,13 @@
1
+ ActiveRecord::Schema.define do
2
+ self.verbose = false
3
+
4
+ create_table :addresses, :force => true do |t|
5
+ t.string :can_be_type
6
+ t.timestamps
7
+ end
8
+
9
+ create_table :people, :force => true do |t|
10
+ t.string :gender
11
+ t.timestamps
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: can_be
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mark Starkman
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '2.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: sqlite3
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: database_cleaner
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: activerecord
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: '3.1'
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '3.1'
94
+ - !ruby/object:Gem::Dependency
95
+ name: activesupport
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '3.1'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '3.1'
110
+ description: Adds helper methods to your Active Record models to control the type
111
+ of record.
112
+ email:
113
+ - mrstarkman@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - .gitignore
119
+ - .rspec
120
+ - .travis.yml
121
+ - Gemfile
122
+ - LICENSE.txt
123
+ - README.md
124
+ - Rakefile
125
+ - can_be.gemspec
126
+ - lib/can_be.rb
127
+ - lib/can_be/initializer.rb
128
+ - lib/can_be/model_extensions.rb
129
+ - lib/can_be/railtie.rb
130
+ - lib/can_be/version.rb
131
+ - log/.gitkeep
132
+ - spec/can_be/model_additions_spec.rb
133
+ - spec/can_be_spec.rb
134
+ - spec/spec_helper.rb
135
+ - spec/support/model_macros.rb
136
+ - spec/support/models.rb
137
+ - spec/support/schema.rb
138
+ homepage: ''
139
+ licenses: []
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ none: false
152
+ requirements:
153
+ - - ! '>='
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ requirements: []
157
+ rubyforge_project:
158
+ rubygems_version: 1.8.23
159
+ signing_key:
160
+ specification_version: 3
161
+ summary: Adds helper methods to your Active Record models to control the type of record.
162
+ test_files:
163
+ - spec/can_be/model_additions_spec.rb
164
+ - spec/can_be_spec.rb
165
+ - spec/spec_helper.rb
166
+ - spec/support/model_macros.rb
167
+ - spec/support/models.rb
168
+ - spec/support/schema.rb