attr_enumerator 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -4,10 +4,10 @@ A method for restricting an attribute to a set of choices.
4
4
 
5
5
  An invocation of <tt>attr_enumerator</tt> will create:
6
6
 
7
- * A <b>validation</b> requiring the attribute value to be one of the provided choices
8
- * A <b>class constant</b> containing all valid choices
9
- * <b>Instance methods</b> for each choice, returning <tt>true</tt> if the attribute is that value and <tt>false</tt> otherwise
10
- * <b>Scopes</b> for each choice that retrieve records where the attribute is that value (only applicable when used with <tt>ActiveRecord</tt>)
7
+ * a <b>class constant</b> containing all valid choices
8
+ * a <b>validation</b> requiring the attribute's value to be one of the choices
9
+ * <b>instance methods</b> for each choice, returning <tt>true</tt> if the attribute is that value and <tt>false</tt> otherwise
10
+ * <b>scopes</b> for each choice that retrieve records where the attribute is that value
11
11
 
12
12
  == Example
13
13
 
@@ -15,26 +15,30 @@ An invocation of <tt>attr_enumerator</tt> will create:
15
15
  attr_enumerator :color, ['red', 'blue']
16
16
  end
17
17
 
18
+ # constant
19
+ Car::COLORS # => ['red', 'blue']
20
+
21
+ # validation
18
22
  car = Car.new
23
+ car.color = 'green'
24
+ car.valid? # => false
25
+ car.errors # => {:color => ["is invalid"]}
19
26
  car.color = 'red'
27
+ car.valid? # => true
20
28
 
21
- car.color_red? # => true
22
- car.color_blue? # => false
23
-
24
- Car::COLORS # => ['red', 'blue']
29
+ # instance methods
30
+ car.red? # => true
31
+ car.blue? # => false
25
32
 
33
+ # scopes
26
34
  car.save
27
- Car.color_red # => [<#Car>]
28
-
29
- car.color = 'green'
30
- car.valid? # => false
31
- car.errors # => #<OrderedHash {:color=>["is invalid"]}>
35
+ Car.red # => [<#Car>]
32
36
 
33
37
  == With or without ActiveRecord
34
38
 
35
- The <tt>AttrEnumerator</tt> module is automatically included in <tt>ActiveRecord::Base</tt> and is available for use in all ActiveRecord models.
39
+ The <tt>AttrEnumerator</tt> module will be automatically included in <tt>ActiveRecord::Base</tt>, making the <tt>attr_enumerator</tt> method available in all ActiveRecord models.
36
40
 
37
- To use <tt>attr_enumerator</tt> on a non-ActiveRecord model the class must include <tt>ActiveModel::Validations</tt> and provide an accessor to the attribute.
41
+ To include <tt>AttrEnumerator</tt> on a non-ActiveRecord model the class must also include <tt>ActiveModel::Validations</tt> and provide an accessor to the attribute. The model will have all the above functionality except no scopes will be generated.
38
42
 
39
43
  class Car
40
44
  include ActiveModel::Validations
@@ -46,17 +50,17 @@ To use <tt>attr_enumerator</tt> on a non-ActiveRecord model the class must inclu
46
50
 
47
51
  == Configuration
48
52
 
49
- An options hash may be passed as the last argument to <tt>attr_enumerator</tt> to configure its behavior. For example:
53
+ Options may be passed as the last argument to <tt>attr_enumerator</tt> to configure its behavior. For example:
50
54
 
51
55
  class Car < ActiveRecord::Base
52
- attr_enumerator :color, ['red', 'blue'], :constant => :PAINT_COLORS, :prefix => :colored
56
+ attr_enumerator :color, ['red', 'blue'], :constant => :PAINT_COLORS, :prefix => :painted
53
57
  end
54
58
 
55
- Car::PAINT_COLORS # => ['red', 'blue']
59
+ Car::PAINT_COLORS # => ['red', 'blue']
56
60
 
57
61
  car = Car.new
58
62
  car.color = 'red'
59
- car.colored_red? # => true
63
+ car.painted_red? # => true
60
64
 
61
65
  === Options
62
66
 
@@ -64,30 +68,22 @@ An options hash may be passed as the last argument to <tt>attr_enumerator</tt> t
64
68
 
65
69
  Set a custom constant name.
66
70
 
67
- * <tt>prefix</tt> (default: attribute name)
71
+ * <tt>prefix</tt> (default: <tt>nil</tt>)
68
72
 
69
- Set a custom prefix for methods and scopes. Set to <tt>false</tt> to disable.
73
+ Set a prefix for generated methods and scopes.
70
74
 
71
75
  * <tt>message</tt> (default: internationalized <tt>"is invalid"</tt>)
72
76
 
73
77
  Set the validation error message when the attribute is not a valid value. Use <tt>%{value}</tt> to refer to the value of the attribute, e.g. <tt>"%{value} is not a valid choice"</tt>.
74
78
 
75
- * <tt>allow_nil</tt> (default: <tt>false</tt>)
79
+ * <tt>allow_nil</tt> / <tt>allow_blank</tt> (default: <tt>false</tt>)
76
80
 
77
- Allow the attribute to be <tt>nil</tt>.
81
+ Do not fail validation when the attribute is <tt>nil</tt> or blank.
78
82
 
79
- * <tt>allow_blank</tt> (default: <tt>false</tt>)
80
-
81
- Allow the attribute to be blank.
82
-
83
- * <tt>if</tt> (default: unused)
83
+ * <tt>if</tt> / <tt>unless</tt> (default: unused)
84
84
 
85
85
  Set a method, proc or string to call to determine if the validation should occur. See <tt>ActiveModel::Validations</tt> for more details.
86
86
 
87
- * <tt>unless</tt> (default: unused)
88
-
89
- Set a method, proc or string to call to determine if the validation should <em>not</em> occur.
90
-
91
87
  == Contributing to attr_enumerator
92
88
 
93
89
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.1
1
+ 0.5.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{attr_enumerator}
8
- s.version = "0.4.1"
8
+ s.version = "0.5.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Chris Baker"]
12
- s.date = %q{2011-05-06}
12
+ s.date = %q{2011-07-07}
13
13
  s.description = %q{A method for restricting an attribute to a set of choices}
14
14
  s.email = %q{baker.chris.3@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -5,27 +5,19 @@ module AttrEnumerator
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  module ClassMethods
8
- def attr_enumerator(field, choices, options = {})
9
- constant = options.delete(:constant) || field.to_s.pluralize.upcase
8
+ def attr_enumerator(attribute, choices, options = {})
9
+ constant = options.delete(:constant) || attribute.to_s.pluralize.upcase
10
+ prefix = options[:prefix] ? options.delete(:prefix).to_s + '_' : ''
11
+ options[:message] ||= :invalid
12
+
10
13
  const_set(constant, choices).freeze
11
-
12
- raw_prefix = options.delete(:prefix)
13
-
14
- prefix = case raw_prefix
15
- when false, '' then ''
16
- when nil then field.to_s + '_'
17
- else raw_prefix.to_s + '_'
18
- end
14
+ validates_inclusion_of attribute, options.merge(:in => choices)
19
15
 
20
16
  choices.each do |choice|
21
- formatted_choice = prefix + choice.to_s.underscore.parameterize('_')
22
-
23
- define_method(formatted_choice + '?') { self.send(field) == choice }
24
- scope formatted_choice, where(field => choice) if self.respond_to? :scope
17
+ choice_string = prefix + choice.to_s.underscore.parameterize('_')
18
+ define_method(choice_string + '?') { send(attribute) == choice }
19
+ scope choice_string, where(attribute => choice) if respond_to? :scope
25
20
  end
26
-
27
- options[:message] ||= :invalid
28
- validates field, :inclusion => options.merge(:in => choices)
29
21
  end
30
22
  end
31
23
  end
@@ -1,119 +1,110 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "AttrEnumerator" do
4
- subject { TestModel }
5
-
6
- def instance
7
- @instance ||= subject.new
8
- end
9
-
10
- after(:each) do
11
- begin
12
- Object.send(:remove_const, :TestModel)
13
- rescue NameError
14
- end
15
- end
4
+ let(:car) { Car.new }
16
5
 
17
6
  context "without ActiveRecord" do
18
7
  before(:each) do
19
- class TestModel
8
+ class Car
20
9
  include ActiveModel::Validations
21
10
  include AttrEnumerator
22
- attr_accessor :choice
11
+ attr_accessor :color
23
12
  end
24
13
  end
14
+
15
+ after(:each) { Object.send(:remove_const, :Car) }
25
16
 
26
17
  context "validation" do
27
18
  it "should pass when the value is one of the choices" do
28
- subject.attr_enumerator :choice, ['red', 'blue']
29
- instance.choice = 'blue'
30
- instance.should be_valid
19
+ Car.attr_enumerator :color, ['red', 'blue']
20
+ car.color = 'blue'
21
+ car.should be_valid
31
22
  end
32
23
 
33
24
  it "should fail when the value is not one of the choices" do
34
- subject.attr_enumerator :choice, ['red', 'blue']
35
- instance.choice = 'green'
36
- instance.should_not be_valid
25
+ Car.attr_enumerator :color, ['red', 'blue']
26
+ car.color = 'green'
27
+ car.should_not be_valid
37
28
  end
38
29
 
39
30
  it "should have a default message" do
40
- subject.attr_enumerator :choice, ['red', 'blue']
41
- instance.valid?
42
- instance.errors.should == {:choice => ['is invalid']}
31
+ Car.attr_enumerator :color, ['red', 'blue']
32
+ car.valid?
33
+ car.errors.should == {:color => ['is invalid']}
43
34
  end
44
35
 
45
36
  it "should allow for a custom message" do
46
- subject.attr_enumerator :choice, ['red', 'blue'], :message => '%{value} is not a valid color'
47
- instance.choice = 'green'
48
- instance.valid?
49
- instance.errors.should == {:choice => ['green is not a valid color']}
37
+ Car.attr_enumerator :color, ['red', 'blue'], :message => '%{value} is not a valid color'
38
+ car.color = 'green'
39
+ car.valid?
40
+ car.errors.should == {:color => ['green is not a valid color']}
50
41
  end
51
42
 
52
43
  it "should handle allow_blank" do
53
- subject.attr_enumerator :choice, ['red', 'blue'], :allow_blank => true
44
+ Car.attr_enumerator :color, ['red', 'blue'], :allow_blank => true
54
45
 
55
- instance.choice = nil
56
- instance.should be_valid
46
+ car.color = nil
47
+ car.should be_valid
57
48
 
58
- instance.choice = ''
59
- instance.should be_valid
49
+ car.color = ''
50
+ car.should be_valid
60
51
  end
61
52
 
62
53
  it "should handle allow_nil" do
63
- subject.attr_enumerator :choice, ['red', 'blue'], :allow_nil => true
54
+ Car.attr_enumerator :color, ['red', 'blue'], :allow_nil => true
64
55
 
65
- instance.choice = nil
66
- instance.should be_valid
56
+ car.color = nil
57
+ car.should be_valid
67
58
 
68
- instance.choice = ''
69
- instance.should_not be_valid
59
+ car.color = ''
60
+ car.should_not be_valid
70
61
  end
71
62
 
72
- it "should handle symbol enumerations distinctively from strings" do
73
- subject.attr_enumerator :choice, [:red, :blue]
63
+ it "should handle symbol choices distinctively from strings" do
64
+ Car.attr_enumerator :color, [:red, :blue]
74
65
 
75
- instance.choice = :red
76
- instance.should be_valid
77
- instance.should be_choice_red
66
+ car.color = :red
67
+ car.should be_valid
68
+ car.should be_red
78
69
 
79
- instance.choice = 'red'
80
- instance.should_not be_valid
81
- instance.should_not be_choice_red
70
+ car.color = 'red'
71
+ car.should_not be_valid
72
+ car.should_not be_red
82
73
  end
83
74
  end
84
75
 
85
76
  context "class constant" do
86
- it "should create a constant by default" do
87
- subject.attr_enumerator :choice, ['red', 'blue']
88
- subject::CHOICES.should == ['red', 'blue']
77
+ it "should create a constant" do
78
+ Car.attr_enumerator :color, ['red', 'blue']
79
+ Car::COLORS.should == ['red', 'blue']
89
80
  end
90
81
 
91
- it "should freeze the constant to prevent editing" do
92
- subject.attr_enumerator :choice, ['red', 'blue']
93
- subject::CHOICES.should be_frozen
82
+ it "should freeze the constant" do
83
+ Car.attr_enumerator :color, ['red', 'blue']
84
+ Car::COLORS.should be_frozen
94
85
  end
95
86
 
96
87
  it "should allow for a custom constant name using a symbol" do
97
- subject.attr_enumerator :choice, ['red', 'blue'], :constant => :POSSIBLE_COLORS
98
- subject::POSSIBLE_COLORS.should == ['red', 'blue']
88
+ Car.attr_enumerator :color, ['red', 'blue'], :constant => :POSSIBLE_COLORS
89
+ Car::POSSIBLE_COLORS.should == ['red', 'blue']
99
90
  end
100
91
 
101
92
  it "should allow for a custom constant name using a string" do
102
- subject.attr_enumerator :choice, ['red', 'blue'], :constant => 'POSSIBLE_COLORS'
103
- subject::POSSIBLE_COLORS.should == ['red', 'blue']
93
+ Car.attr_enumerator :color, ['red', 'blue'], :constant => 'POSSIBLE_COLORS'
94
+ Car::POSSIBLE_COLORS.should == ['red', 'blue']
104
95
  end
105
96
  end
106
97
 
107
98
  context "methods" do
108
- it "should create methods for each enumeration by default" do
109
- subject.attr_enumerator :choice, ['red', 'blue']
110
- instance.choice = 'red'
99
+ it "should create methods for each choice" do
100
+ Car.attr_enumerator :color, ['red', 'blue']
101
+ car.color = 'red'
111
102
 
112
- instance.should respond_to :choice_red?
113
- instance.should be_choice_red
103
+ car.should respond_to :red?
104
+ car.should be_red
114
105
 
115
- instance.should respond_to :choice_blue?
116
- instance.should_not be_choice_blue
106
+ car.should respond_to :blue?
107
+ car.should_not be_blue
117
108
  end
118
109
 
119
110
  it "should create methods with friendly names" do
@@ -126,43 +117,35 @@ describe "AttrEnumerator" do
126
117
  :ends_with_dot? => 'ends.with.dot.'
127
118
  }
128
119
 
129
- subject.attr_enumerator :choice, enumerations.values, :prefix => false
120
+ Car.attr_enumerator :color, enumerations.values
130
121
 
131
122
  enumerations.keys.each do |method_name|
132
- instance.should respond_to method_name
123
+ car.should respond_to method_name
133
124
  end
134
125
  end
135
126
 
136
127
  it "should allow for a custom prefix" do
137
- subject.attr_enumerator :choice, ['red', 'blue'], :prefix => 'colored'
138
- instance.choice = 'red'
128
+ Car.attr_enumerator :color, ['red', 'blue'], :prefix => 'painted'
129
+ car.color = 'red'
139
130
 
140
- instance.should respond_to :colored_red?
141
- instance.should be_colored_red
131
+ car.should respond_to :painted_red?
132
+ car.should be_painted_red
142
133
 
143
- instance.should respond_to :colored_blue?
144
- instance.should_not be_colored_blue
145
- end
146
-
147
- it "should allow for no prefix" do
148
- subject.attr_enumerator :choice, ['red', 'blue'], :prefix => false
149
- instance.choice = 'red'
150
-
151
- instance.should respond_to :red?
152
- instance.should be_red
153
-
154
- instance.should respond_to :blue?
155
- instance.should_not be_blue
134
+ car.should respond_to :painted_blue?
135
+ car.should_not be_painted_blue
156
136
  end
157
137
  end
158
138
  end
159
139
 
160
140
  context "with ActiveRecord" do
161
141
  before(:each) do
162
- class TestModel < ActiveRecordModel
163
- attr_accessor :choice
142
+ class Car < ActiveRecord::Base
143
+ establish_connection(:adapter => 'sqlite3', :database => ':memory:')
144
+ attr_accessor :color
164
145
  end
165
146
  end
147
+
148
+ after(:each) { Object.send(:remove_const, :Car) }
166
149
 
167
150
  it "should automatically be included in ActiveRecord::Base" do
168
151
  ActiveRecord::Base.should respond_to :attr_enumerator
@@ -170,18 +153,13 @@ describe "AttrEnumerator" do
170
153
 
171
154
  describe "scopes" do
172
155
  it "should create a scope for each enumeration" do
173
- subject.attr_enumerator :choice, ['red', 'blue']
174
- subject.choice_red.should be_a ActiveRecord::Relation
175
- end
176
-
177
- it "should create a scope for each enumeration with custom prefix " do
178
- subject.attr_enumerator :choice, ['red', 'blue'], :prefix => 'colored'
179
- subject.colored_red.should be_a ActiveRecord::Relation
156
+ Car.attr_enumerator :color, ['red', 'blue']
157
+ Car.red.should be_a ActiveRecord::Relation
180
158
  end
181
159
 
182
- it "should create a scope for each enumeration without prefix " do
183
- subject.attr_enumerator :choice, ['red', 'blue'], :prefix => false
184
- subject.red.should be_a ActiveRecord::Relation
160
+ it "should allow for scopes with a custom prefix" do
161
+ Car.attr_enumerator :color, ['red', 'blue'], :prefix => 'painted'
162
+ Car.painted_red.should be_a ActiveRecord::Relation
185
163
  end
186
164
  end
187
165
  end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,2 @@
1
1
  require 'active_record'
2
2
  require 'attr_enumerator'
3
-
4
- class ActiveRecordModel < ActiveRecord::Base
5
- establish_connection(:adapter => 'sqlite3', :database => ':memory:')
6
- connection.execute("CREATE TABLE #{table_name} (#{primary_key} integer PRIMARY KEY AUTOINCREMENT)")
7
- end
data/watchr.rb CHANGED
@@ -11,3 +11,5 @@ end
11
11
  watch( '^lib/(.*)\.rb' ) { |m| run("spec/%s_spec.rb" % m[1]) }
12
12
  watch( '^spec/spec_helper\.rb' ) { run_all }
13
13
  watch( '^spec.*/.*_spec\.rb' ) { |m| run(m[0]) }
14
+
15
+ puts "watchr ready"
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attr_enumerator
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 11
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 4
9
- - 1
10
- version: 0.4.1
8
+ - 5
9
+ - 0
10
+ version: 0.5.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Chris Baker
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-06 00:00:00 Z
18
+ date: 2011-07-07 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  type: :runtime