enumerize 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +0 -1
- data/CHANGELOG.md +15 -0
- data/Gemfile +3 -1
- data/Gemfile.rails4 +4 -2
- data/README.md +45 -2
- data/Rakefile +6 -0
- data/enumerize.gemspec +3 -3
- data/lib/enumerize.rb +5 -0
- data/lib/enumerize/activerecord.rb +30 -12
- data/lib/enumerize/attribute.rb +13 -1
- data/lib/enumerize/attribute_map.rb +2 -0
- data/lib/enumerize/base.rb +19 -11
- data/lib/enumerize/integrations/rspec.rb +17 -0
- data/lib/enumerize/integrations/rspec/matcher.rb +76 -0
- data/lib/enumerize/predicatable.rb +30 -0
- data/lib/enumerize/set.rb +9 -0
- data/lib/enumerize/value.rb +8 -27
- data/lib/enumerize/version.rb +1 -1
- data/test/activerecord_test.rb +22 -0
- data/test/base_test.rb +21 -1
- data/test/formtastic_test.rb +1 -0
- data/test/module_attributes_test.rb +21 -0
- data/test/mongo_mapper_test.rb +68 -0
- data/test/mongoid_test.rb +1 -1
- data/test/multiple_test.rb +5 -0
- data/test/predicates_test.rb +13 -0
- data/test/rspec_matcher_test.rb +53 -0
- data/test/rspec_spec.rb +13 -0
- data/test/set_test.rb +38 -0
- data/test/simple_form_test.rb +1 -0
- data/test/test_helper.rb +0 -14
- data/test/value_test.rb +28 -0
- metadata +12 -5
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
## 0.7.0 (August 21, 2013) ##
|
2
|
+
|
3
|
+
### enhancements
|
4
|
+
* Give priority to model specific translation definition. See example [here](https://github.com/brainspec/enumerize/pull/96) (by [@labocho](https://github.com/labocho))
|
5
|
+
* Allow lambda in default value (by [@adie](https://github.com/adie))
|
6
|
+
* Add predicate methods to the multiple attributes (by [@nashby](https://github.com/nashby))
|
7
|
+
* Add RSpec matcher (by [@nashby](https://github.com/nashby))
|
8
|
+
* Add `*_value` method that returns actual value of the enumerized attribute (useful for attributes with custom values)
|
9
|
+
(by [@tkyowa](https://github.com/tkyowa))
|
10
|
+
|
11
|
+
### bug fix
|
12
|
+
* Make validation work when `write_attribute` is using for setting enumerized values (by [@nashby](https://github.com/nashby))
|
13
|
+
* Validates enumerized values when enumeration is included via module
|
14
|
+
(by [@nashby](https://github.com/nashby)) and (by [@lest](https://github.com/lest))
|
15
|
+
|
1
16
|
## 0.6.1 (May 20, 2013) ##
|
2
17
|
|
3
18
|
### bug fix
|
data/Gemfile
CHANGED
@@ -4,11 +4,13 @@ gemspec
|
|
4
4
|
|
5
5
|
gem 'rake'
|
6
6
|
gem 'minitest', '~> 4.1'
|
7
|
+
gem 'rspec', :require => false
|
7
8
|
|
8
|
-
gem '
|
9
|
+
gem 'rails', '~> 3.2.0', :require => false
|
9
10
|
gem 'sqlite3', :platform => [:ruby, :mswin, :mingw]
|
10
11
|
gem 'activerecord-jdbcsqlite3-adapter', :platform => :jruby
|
11
12
|
|
12
13
|
gem 'mongoid'
|
14
|
+
gem 'mongo_mapper'
|
13
15
|
gem 'simple_form'
|
14
16
|
gem 'formtastic'
|
data/Gemfile.rails4
CHANGED
@@ -4,11 +4,13 @@ gemspec
|
|
4
4
|
|
5
5
|
gem 'rake'
|
6
6
|
gem 'minitest', '~> 4.1'
|
7
|
+
gem 'rspec', :require => false
|
7
8
|
|
8
|
-
gem '
|
9
|
+
gem 'rails', '4.0.0', :require => false
|
9
10
|
gem 'sqlite3', :platform => [:ruby, :mswin, :mingw]
|
10
11
|
gem 'activerecord-jdbcsqlite3-adapter', :platform => :jruby
|
11
12
|
|
12
13
|
gem 'mongoid', github: 'mongoid/mongoid'
|
13
|
-
gem '
|
14
|
+
gem 'mongo_mapper', github: 'jnunemaker/mongomapper'
|
15
|
+
gem 'simple_form', github: 'plataformatec/simple_form'
|
14
16
|
gem 'formtastic', github: 'justinfrench/formtastic'
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Enumerize [![TravisCI](https://secure.travis-ci.org/brainspec/enumerize.png?branch=master)](http://travis-ci.org/brainspec/enumerize) [![Gemnasium](https://gemnasium.com/brainspec/enumerize.png)](https://gemnasium.com/brainspec/enumerize)
|
2
2
|
|
3
|
-
Enumerated attributes with I18n and ActiveRecord/Mongoid support
|
3
|
+
Enumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper support
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -34,7 +34,7 @@ ActiveRecord:
|
|
34
34
|
class User < ActiveRecord::Base
|
35
35
|
extend Enumerize
|
36
36
|
|
37
|
-
enumerize :sex, in: [:male, :female]
|
37
|
+
enumerize :sex, in: [:male, :female], default: lambda { |user| SexIdentifier.sex_for_name(user.name).to_sym }
|
38
38
|
|
39
39
|
enumerize :role, in: [:user, :admin], default: :user
|
40
40
|
end
|
@@ -52,6 +52,18 @@ class User
|
|
52
52
|
end
|
53
53
|
```
|
54
54
|
|
55
|
+
MongoMapper:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
class User
|
59
|
+
include MongoMapper::Document
|
60
|
+
extend Enumerize
|
61
|
+
|
62
|
+
key :role
|
63
|
+
enumerize :role, in: [:user, :admin], default: :user
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
55
67
|
I18n:
|
56
68
|
|
57
69
|
```ruby
|
@@ -73,6 +85,15 @@ en:
|
|
73
85
|
female: "Female"
|
74
86
|
```
|
75
87
|
|
88
|
+
Note that if you want to use I18n feature with plain Ruby object don't forget to extend it with `ActiveModel::Naming`:
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
class User
|
92
|
+
extend Enumerize
|
93
|
+
extend ActiveModel::Naming
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
76
97
|
get attribute value:
|
77
98
|
|
78
99
|
```ruby
|
@@ -162,6 +183,11 @@ class User < ActiveRecord::Base
|
|
162
183
|
|
163
184
|
enumerize :role, in: {:user => 1, :admin => 2}
|
164
185
|
end
|
186
|
+
|
187
|
+
user = User.new
|
188
|
+
user.role = :user
|
189
|
+
user.role #=> 'user'
|
190
|
+
user.role_value #=> 1
|
165
191
|
```
|
166
192
|
|
167
193
|
ActiveRecord scopes:
|
@@ -244,6 +270,23 @@ and if you want it as radio buttons:
|
|
244
270
|
<% end %>
|
245
271
|
```
|
246
272
|
|
273
|
+
### RSpec
|
274
|
+
|
275
|
+
Also you can use builtin RSpec matcher:
|
276
|
+
|
277
|
+
```ruby
|
278
|
+
class User
|
279
|
+
extend Enumerize
|
280
|
+
|
281
|
+
enumerize :sex, in: [:male, :female], default: :male
|
282
|
+
end
|
283
|
+
|
284
|
+
describe User do
|
285
|
+
it { should enumerize(:sex).in(:male, :female) }
|
286
|
+
it { should enumerize(:sex).in(:male, :female).with_default(:male) }
|
287
|
+
end
|
288
|
+
```
|
289
|
+
|
247
290
|
### Other Integrations
|
248
291
|
|
249
292
|
Enumerize integrates with the following automatically:
|
data/Rakefile
CHANGED
@@ -2,10 +2,16 @@
|
|
2
2
|
require "bundler/gem_tasks"
|
3
3
|
|
4
4
|
require 'rake/testtask'
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
|
5
7
|
Rake::TestTask.new do |t|
|
6
8
|
t.libs << 'test'
|
7
9
|
t.pattern = 'test/*_test.rb'
|
8
10
|
t.verbose = true
|
9
11
|
end
|
10
12
|
|
13
|
+
RSpec::Core::RakeTask.new('default') do |t|
|
14
|
+
t.pattern = FileList['test/rspec_spec.rb']
|
15
|
+
end
|
16
|
+
|
11
17
|
task :default => :test
|
data/enumerize.gemspec
CHANGED
@@ -4,8 +4,8 @@ require File.expand_path('../lib/enumerize/version', __FILE__)
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.authors = ["Sergey Nartimov"]
|
6
6
|
gem.email = "team@brainspec.com"
|
7
|
-
gem.description = %q{Enumerated attributes with I18n and ActiveRecord/Mongoid support}
|
8
|
-
gem.summary = %q{Enumerated attributes with I18n and ActiveRecord/Mongoid support}
|
7
|
+
gem.description = %q{Enumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper support}
|
8
|
+
gem.summary = %q{Enumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper support}
|
9
9
|
gem.homepage = "https://github.com/brainspec/enumerize"
|
10
10
|
|
11
11
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
@@ -14,7 +14,7 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.name = "enumerize"
|
15
15
|
gem.require_paths = ["lib"]
|
16
16
|
gem.version = Enumerize::VERSION
|
17
|
-
|
17
|
+
|
18
18
|
gem.required_ruby_version = '>= 1.9.3'
|
19
19
|
|
20
20
|
gem.add_dependency('activesupport', '>= 3.2')
|
data/lib/enumerize.rb
CHANGED
@@ -10,6 +10,7 @@ module Enumerize
|
|
10
10
|
autoload :Module, 'enumerize/module'
|
11
11
|
autoload :ActiveRecord, 'enumerize/activerecord'
|
12
12
|
autoload :Predicates, 'enumerize/predicates'
|
13
|
+
autoload :Predicatable, 'enumerize/predicatable'
|
13
14
|
autoload :ModuleAttributes, 'enumerize/module_attributes'
|
14
15
|
|
15
16
|
def self.included(base)
|
@@ -47,4 +48,8 @@ module Enumerize
|
|
47
48
|
require 'enumerize/hooks/formtastic'
|
48
49
|
rescue LoadError
|
49
50
|
end
|
51
|
+
|
52
|
+
if defined?(::RSpec)
|
53
|
+
require 'enumerize/integrations/rspec'
|
54
|
+
end
|
50
55
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'active_support/concern'
|
2
|
-
|
3
1
|
module Enumerize
|
4
2
|
module ActiveRecord
|
5
3
|
def enumerize(name, options={})
|
@@ -8,23 +6,43 @@ module Enumerize
|
|
8
6
|
if options[:scope]
|
9
7
|
_enumerize_module.dependent_eval do
|
10
8
|
if defined?(::ActiveRecord::Base) && self < ::ActiveRecord::Base
|
11
|
-
|
12
|
-
define_singleton_method scope_name do |*values|
|
13
|
-
values = values.map { |value| enumerized_attributes[name].find_value(value).value }
|
14
|
-
values = values.first if values.size == 1
|
9
|
+
_define_scope_methods!(name, options)
|
15
10
|
|
16
|
-
|
17
|
-
|
11
|
+
class_eval do
|
12
|
+
# https://github.com/brainspec/enumerize/issues/74
|
13
|
+
def write_attribute(attr_name, value)
|
14
|
+
_enumerized_values_for_validation[attr_name] = value
|
18
15
|
|
19
|
-
|
20
|
-
define_singleton_method "without_#{name}" do |*values|
|
21
|
-
values = values.map { |value| enumerized_attributes[name].find_value(value).value }
|
22
|
-
where(arel_table[name].not_in(values))
|
16
|
+
super
|
23
17
|
end
|
18
|
+
|
19
|
+
# Since Rails use `allocate` method on models and initializes them with `init_with` method.
|
20
|
+
# This way `initialize` method is not being called, but `after_initialize` callback always gets triggered.
|
21
|
+
after_initialize :_set_default_value_for_enumerized_attributes
|
24
22
|
end
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
28
26
|
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def _define_scope_methods!(name, options)
|
31
|
+
scope_name = options[:scope] == true ? "with_#{name}" : options[:scope]
|
32
|
+
|
33
|
+
define_singleton_method scope_name do |*values|
|
34
|
+
values = values.map { |value| enumerized_attributes[name].find_value(value).value }
|
35
|
+
values = values.first if values.size == 1
|
36
|
+
|
37
|
+
where(name => values)
|
38
|
+
end
|
39
|
+
|
40
|
+
if options[:scope] == true
|
41
|
+
define_singleton_method "without_#{name}" do |*values|
|
42
|
+
values = values.map { |value| enumerized_attributes[name].find_value(value).value }
|
43
|
+
where(arel_table[name].not_in(values))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
29
47
|
end
|
30
48
|
end
|
data/lib/enumerize/attribute.rb
CHANGED
@@ -14,11 +14,19 @@ module Enumerize
|
|
14
14
|
@value_hash.merge! Hash[@values.map { |v| [v.to_s, v] }]
|
15
15
|
|
16
16
|
if options[:default]
|
17
|
-
@default_value =
|
17
|
+
@default_value = find_default_value(options[:default])
|
18
18
|
raise ArgumentError, 'invalid default value' unless @default_value
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
def find_default_value(value)
|
23
|
+
if value.respond_to?(:call)
|
24
|
+
value
|
25
|
+
else
|
26
|
+
find_value(value)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
22
30
|
def find_value(value)
|
23
31
|
@value_hash[value.to_s] unless value.nil?
|
24
32
|
end
|
@@ -82,6 +90,10 @@ module Enumerize
|
|
82
90
|
def #{name}_text
|
83
91
|
self.#{name} && self.#{name}.text
|
84
92
|
end
|
93
|
+
|
94
|
+
def #{name}_value
|
95
|
+
self.#{name} && self.#{name}.value
|
96
|
+
end
|
85
97
|
RUBY
|
86
98
|
end
|
87
99
|
end
|
data/lib/enumerize/base.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
require 'active_support/concern'
|
2
|
-
|
3
1
|
module Enumerize
|
4
2
|
module Base
|
5
|
-
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
validate :_validate_enumerized_attributes
|
6
|
+
if base.respond_to?(:validate)
|
7
|
+
base.validate :_validate_enumerized_attributes
|
10
8
|
end
|
11
9
|
end
|
12
10
|
|
@@ -48,11 +46,7 @@ module Enumerize
|
|
48
46
|
|
49
47
|
def initialize(*)
|
50
48
|
super
|
51
|
-
|
52
|
-
if !public_send(attr.name) && !_enumerized_values_for_validation.key?(attr.name)
|
53
|
-
public_send("#{attr.name}=", attr.default_value)
|
54
|
-
end
|
55
|
-
end
|
49
|
+
_set_default_value_for_enumerized_attributes
|
56
50
|
end
|
57
51
|
|
58
52
|
def read_attribute_for_validation(key)
|
@@ -81,5 +75,19 @@ module Enumerize
|
|
81
75
|
end
|
82
76
|
end
|
83
77
|
end
|
78
|
+
|
79
|
+
def _set_default_value_for_enumerized_attributes
|
80
|
+
self.class.enumerized_attributes.each do |attr|
|
81
|
+
if !public_send(attr.name) && !_enumerized_values_for_validation.key?(attr.name)
|
82
|
+
value = attr.default_value
|
83
|
+
|
84
|
+
if value.respond_to?(:call)
|
85
|
+
value = value.arity == 0 ? value.call : value.call(self)
|
86
|
+
end
|
87
|
+
|
88
|
+
public_send("#{attr.name}=", value)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
84
92
|
end
|
85
93
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'enumerize/integrations/rspec/matcher'
|
2
|
+
|
3
|
+
module Enumerize
|
4
|
+
module Integrations
|
5
|
+
module RSpec
|
6
|
+
def enumerize(attr)
|
7
|
+
::Enumerize::Integrations::RSpec::Matcher.new(attr)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module RSpec
|
14
|
+
module Matchers
|
15
|
+
include Enumerize::Integrations::RSpec
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Enumerize
|
2
|
+
module Integrations
|
3
|
+
module RSpec
|
4
|
+
class Matcher
|
5
|
+
attr_accessor :attr, :values, :subject, :default
|
6
|
+
|
7
|
+
def initialize(attr)
|
8
|
+
self.attr = attr
|
9
|
+
end
|
10
|
+
|
11
|
+
def in(*values)
|
12
|
+
self.values = values.map(&:to_s).sort
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
def with_default(default)
|
17
|
+
self.default = default.to_s
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def failure_message
|
22
|
+
message = " expected :#{attr} to allow value#{values.size == 1 ? nil : 's'}: #{quote_values(values)},"
|
23
|
+
message += " but it allows #{quote_values(enumerized_values)} instead"
|
24
|
+
|
25
|
+
if default
|
26
|
+
message = " expected :#{attr} to have #{default.inspect} as default value,"
|
27
|
+
message += " but it sets #{enumerized_default.inspect} instead"
|
28
|
+
end
|
29
|
+
|
30
|
+
message
|
31
|
+
end
|
32
|
+
|
33
|
+
def description
|
34
|
+
description = "enumerize :#{attr} in: #{quote_values(values)}"
|
35
|
+
description += " with #{default.inspect} as default value" if default
|
36
|
+
end
|
37
|
+
|
38
|
+
def matches?(subject)
|
39
|
+
self.subject = subject
|
40
|
+
matches = true
|
41
|
+
|
42
|
+
matches &= matches_attributes?
|
43
|
+
matches &= matches_default_value? if default
|
44
|
+
|
45
|
+
matches
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def matches_attributes?
|
51
|
+
values == enumerized_values
|
52
|
+
end
|
53
|
+
|
54
|
+
def matches_default_value?
|
55
|
+
default == enumerized_default
|
56
|
+
end
|
57
|
+
|
58
|
+
def enumerized_values
|
59
|
+
@enumerized_values ||= attributes[attr.to_s].values.sort
|
60
|
+
end
|
61
|
+
|
62
|
+
def enumerized_default
|
63
|
+
@enumerized_default ||= attributes[attr.to_s].default_value
|
64
|
+
end
|
65
|
+
|
66
|
+
def attributes
|
67
|
+
subject.class.enumerized_attributes.attributes
|
68
|
+
end
|
69
|
+
|
70
|
+
def quote_values(values)
|
71
|
+
values.map(&:inspect).join(', ')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Enumerize
|
2
|
+
module Predicatable
|
3
|
+
def method_missing(method, *args, &block)
|
4
|
+
if boolean_method?(method)
|
5
|
+
define_query_methods
|
6
|
+
send(method, *args, &block)
|
7
|
+
else
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def respond_to_missing?(method, include_private=false)
|
13
|
+
boolean_method?(method)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def define_query_methods
|
19
|
+
@attr.values.each do |value|
|
20
|
+
unless singleton_methods.include?(:"#{value}?")
|
21
|
+
define_query_method(value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def boolean_method?(method)
|
27
|
+
method[-1] == '?' && @attr.values.include?(method[0..-2])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/enumerize/set.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Enumerize
|
2
2
|
class Set
|
3
3
|
include Enumerable
|
4
|
+
include Predicatable
|
4
5
|
|
5
6
|
attr_reader :values
|
6
7
|
|
@@ -53,6 +54,14 @@ module Enumerize
|
|
53
54
|
|
54
55
|
private
|
55
56
|
|
57
|
+
def define_query_method(value)
|
58
|
+
singleton_class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
59
|
+
def #{value}?
|
60
|
+
include?("#{value}")
|
61
|
+
end
|
62
|
+
RUBY
|
63
|
+
end
|
64
|
+
|
56
65
|
def mutate!
|
57
66
|
@values = @obj.public_send("#{@attr.name}=", @values).values
|
58
67
|
end
|
data/lib/enumerize/value.rb
CHANGED
@@ -2,6 +2,8 @@ require 'i18n'
|
|
2
2
|
|
3
3
|
module Enumerize
|
4
4
|
class Value < String
|
5
|
+
include Predicatable
|
6
|
+
|
5
7
|
def initialize(attr, name, value=nil)
|
6
8
|
@attr = attr
|
7
9
|
@value = value || name.to_s
|
@@ -17,38 +19,21 @@ module Enumerize
|
|
17
19
|
I18n.t(i18n_keys[0], :default => i18n_keys[1..-1])
|
18
20
|
end
|
19
21
|
|
20
|
-
def method_missing(method, *args, &block)
|
21
|
-
if boolean_method?(method)
|
22
|
-
define_query_methods
|
23
|
-
send(method, *args, &block)
|
24
|
-
else
|
25
|
-
super
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def respond_to_missing?(method, include_private=false)
|
30
|
-
boolean_method?(method)
|
31
|
-
end
|
32
|
-
|
33
22
|
private
|
34
23
|
|
35
|
-
def
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
def #{value}?
|
40
|
-
#{value == self}
|
41
|
-
end
|
42
|
-
RUBY
|
24
|
+
def define_query_method(value)
|
25
|
+
singleton_class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
26
|
+
def #{value}?
|
27
|
+
#{value == self}
|
43
28
|
end
|
44
|
-
|
29
|
+
RUBY
|
45
30
|
end
|
46
31
|
|
47
32
|
def i18n_keys
|
48
33
|
@i18n_keys ||= begin
|
49
34
|
i18n_keys = []
|
50
|
-
i18n_keys << i18n_scope
|
51
35
|
i18n_keys << i18n_scope(i18n_suffix)
|
36
|
+
i18n_keys << i18n_scope
|
52
37
|
i18n_keys << self.humanize # humanize value if there are no translations
|
53
38
|
end
|
54
39
|
end
|
@@ -60,9 +45,5 @@ module Enumerize
|
|
60
45
|
def i18n_suffix
|
61
46
|
"#{@attr.i18n_suffix}." if @attr.i18n_suffix
|
62
47
|
end
|
63
|
-
|
64
|
-
def boolean_method?(method)
|
65
|
-
method[-1] == '?' && @attr.values.include?(method[0..-2])
|
66
|
-
end
|
67
48
|
end
|
68
49
|
end
|
data/lib/enumerize/version.rb
CHANGED
data/test/activerecord_test.rb
CHANGED
@@ -12,6 +12,7 @@ ActiveRecord::Base.connection.instance_eval do
|
|
12
12
|
create_table :users do |t|
|
13
13
|
t.string :sex
|
14
14
|
t.string :role
|
15
|
+
t.string :lambda_role
|
15
16
|
t.string :name
|
16
17
|
t.string :interests
|
17
18
|
t.string :status
|
@@ -36,6 +37,7 @@ end
|
|
36
37
|
module RoleEnum
|
37
38
|
extend Enumerize
|
38
39
|
enumerize :role, :in => [:user, :admin], :default => :user, scope: :having_role
|
40
|
+
enumerize :lambda_role, :in => [:user, :admin], :default => lambda { :admin }
|
39
41
|
end
|
40
42
|
|
41
43
|
class User < ActiveRecord::Base
|
@@ -82,6 +84,19 @@ describe Enumerize::ActiveRecord do
|
|
82
84
|
User.new.attributes['role'].must_equal 'user'
|
83
85
|
end
|
84
86
|
|
87
|
+
it 'has default value with lambda' do
|
88
|
+
User.new.lambda_role.must_equal 'admin'
|
89
|
+
User.new.attributes['lambda_role'].must_equal 'admin'
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'uses after_initialize callback to set default value' do
|
93
|
+
User.delete_all
|
94
|
+
User.create!(sex: 'male', lambda_role: nil)
|
95
|
+
|
96
|
+
user = User.where(:sex => 'male').first
|
97
|
+
user.lambda_role.must_equal 'admin'
|
98
|
+
end
|
99
|
+
|
85
100
|
it 'uses default value from db column' do
|
86
101
|
User.new.account_type.must_equal 'basic'
|
87
102
|
end
|
@@ -102,6 +117,13 @@ describe Enumerize::ActiveRecord do
|
|
102
117
|
user.errors[:role].must_include 'is not included in the list'
|
103
118
|
end
|
104
119
|
|
120
|
+
it 'validates inclusion when using write_attribute' do
|
121
|
+
user = User.new
|
122
|
+
user.send(:write_attribute, :role, 'wrong')
|
123
|
+
user.wont_be :valid?
|
124
|
+
user.errors[:role].must_include 'is not included in the list'
|
125
|
+
end
|
126
|
+
|
105
127
|
it 'validates inclusion on mass assignment' do
|
106
128
|
assert_raises ActiveRecord::RecordInvalid do
|
107
129
|
User.create!(role: 'wrong')
|
data/test/base_test.rb
CHANGED
@@ -78,6 +78,16 @@ describe Enumerize::Base do
|
|
78
78
|
object.foo.must_equal 'b'
|
79
79
|
end
|
80
80
|
|
81
|
+
it 'handles default value with lambda' do
|
82
|
+
klass.enumerize(:foo, :in => [:a, :b], :default => lambda { :b })
|
83
|
+
object.foo.must_equal 'b'
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'injects object instance into lamda default value' do
|
87
|
+
klass.enumerize(:foo, :in => [:a, :b], :default => lambda { |obj| :b if obj.is_a? klass })
|
88
|
+
object.foo.must_equal 'b'
|
89
|
+
end
|
90
|
+
|
81
91
|
it 'raises exception on invalid default value' do
|
82
92
|
proc {
|
83
93
|
klass.enumerize(:foo, :in => [:a, :b], :default => :c)
|
@@ -168,7 +178,7 @@ describe Enumerize::Base do
|
|
168
178
|
object.attributes.must_equal(:foo => 'test')
|
169
179
|
end
|
170
180
|
|
171
|
-
it '
|
181
|
+
it 'stores hash values' do
|
172
182
|
klass.enumerize(:foo, :in => {:a => 1, :b => 2})
|
173
183
|
|
174
184
|
object.foo = :a
|
@@ -179,4 +189,14 @@ describe Enumerize::Base do
|
|
179
189
|
object.instance_variable_get(:@foo).must_equal 2
|
180
190
|
object.foo.must_equal 'b'
|
181
191
|
end
|
192
|
+
|
193
|
+
it 'returns custom value' do
|
194
|
+
klass.enumerize(:foo, :in => {:a => 1, :b => 2})
|
195
|
+
|
196
|
+
object.foo = :a
|
197
|
+
object.foo_value.must_equal 1
|
198
|
+
|
199
|
+
object.foo = :b
|
200
|
+
object.foo_value.must_equal 2
|
201
|
+
end
|
182
202
|
end
|
data/test/formtastic_test.rb
CHANGED
@@ -26,4 +26,25 @@ class ModuleAttributesSpec < MiniTest::Spec
|
|
26
26
|
klass.new.sex.must_equal 'male'
|
27
27
|
klass.sex.must_be_instance_of Enumerize::Attribute
|
28
28
|
end
|
29
|
+
|
30
|
+
it 'validates attributes' do
|
31
|
+
mod = Module.new do
|
32
|
+
extend Enumerize
|
33
|
+
enumerize :sex, :in => %w[male female]
|
34
|
+
end
|
35
|
+
|
36
|
+
klass = Class.new do
|
37
|
+
include ActiveModel::Validations
|
38
|
+
include mod
|
39
|
+
|
40
|
+
def self.model_name
|
41
|
+
ActiveModel::Name.new(self, nil, 'name')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
object = klass.new
|
46
|
+
object.sex = 'wrong'
|
47
|
+
object.wont_be :valid?
|
48
|
+
object.errors[:sex].must_include 'is not included in the list'
|
49
|
+
end
|
29
50
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
silence_warnings do
|
4
|
+
require 'mongo_mapper'
|
5
|
+
end
|
6
|
+
|
7
|
+
MongoMapper.connection = Mongo::Connection.new('localhost', 27017)
|
8
|
+
MongoMapper.database = 'enumerize-test-suite-of-mongomapper'
|
9
|
+
|
10
|
+
describe Enumerize do
|
11
|
+
class MongoMapperUser
|
12
|
+
include MongoMapper::Document
|
13
|
+
extend Enumerize
|
14
|
+
|
15
|
+
key :sex
|
16
|
+
key :role
|
17
|
+
|
18
|
+
enumerize :sex, :in => %w[male female]
|
19
|
+
enumerize :role, :in => %w[admin user], :default => 'user'
|
20
|
+
end
|
21
|
+
|
22
|
+
before { $VERBOSE = nil }
|
23
|
+
after { $VERBOSE = true }
|
24
|
+
|
25
|
+
let(:model) { MongoMapperUser }
|
26
|
+
|
27
|
+
it 'sets nil if invalid value is passed' do
|
28
|
+
user = model.new
|
29
|
+
user.sex = :invalid
|
30
|
+
user.sex.must_equal nil
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'saves value' do
|
34
|
+
model.delete_all
|
35
|
+
user = model.new
|
36
|
+
user.sex = :female
|
37
|
+
user.save!
|
38
|
+
user.sex.must_equal 'female'
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'loads value' do
|
42
|
+
model.delete_all
|
43
|
+
model.create!(:sex => :male)
|
44
|
+
store_translations(:en, :enumerize => {:sex => {:male => 'Male'}}) do
|
45
|
+
user = model.first
|
46
|
+
user.sex.must_equal 'male'
|
47
|
+
user.sex_text.must_equal 'Male'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'has default value' do
|
52
|
+
model.new.role.must_equal 'user'
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'validates inclusion' do
|
56
|
+
user = model.new
|
57
|
+
user.role = 'wrong'
|
58
|
+
user.wont_be :valid?
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'assigns value on loaded record' do
|
62
|
+
model.delete_all
|
63
|
+
model.create!(:sex => :male)
|
64
|
+
user = model.first
|
65
|
+
user.sex = :female
|
66
|
+
user.sex.must_equal 'female'
|
67
|
+
end
|
68
|
+
end
|
data/test/mongoid_test.rb
CHANGED
data/test/multiple_test.rb
CHANGED
@@ -28,4 +28,9 @@ describe Enumerize::Base do
|
|
28
28
|
klass.enumerize :foos, in: %w(a b c), multiple: true
|
29
29
|
object.wont_respond_to :foos_text
|
30
30
|
end
|
31
|
+
|
32
|
+
it "doesn't define _value method" do
|
33
|
+
klass.enumerize :foos, in: %w(a b c), multiple: true
|
34
|
+
object.wont_respond_to :foos_value
|
35
|
+
end
|
31
36
|
end
|
data/test/predicates_test.rb
CHANGED
@@ -15,6 +15,12 @@ describe Enumerize::Predicates do
|
|
15
15
|
object.must_respond_to :b?
|
16
16
|
end
|
17
17
|
|
18
|
+
it 'creates predicate methods on multiple attribute' do
|
19
|
+
klass.enumerize(:foo, in: %w(a b), predicates: true, multiple: true)
|
20
|
+
object.must_respond_to :a?
|
21
|
+
object.must_respond_to :b?
|
22
|
+
end
|
23
|
+
|
18
24
|
it 'checks values' do
|
19
25
|
klass.enumerize(:foo, in: %w(a b), predicates: true)
|
20
26
|
object.foo = 'a'
|
@@ -22,6 +28,13 @@ describe Enumerize::Predicates do
|
|
22
28
|
object.b?.must_equal false
|
23
29
|
end
|
24
30
|
|
31
|
+
it 'checks values on multiple attribute' do
|
32
|
+
klass.enumerize(:foo, in: %w(a b), predicates: true, multiple: true)
|
33
|
+
object.foo << :a
|
34
|
+
object.a?.must_equal true
|
35
|
+
object.b?.must_equal false
|
36
|
+
end
|
37
|
+
|
25
38
|
it 'prefixes methods' do
|
26
39
|
klass.enumerize(:foo, in: %w(a b), predicates: { prefix: 'bar' })
|
27
40
|
object.wont_respond_to :a?
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'enumerize/integrations/rspec'
|
3
|
+
|
4
|
+
describe Enumerize::Integrations::RSpec do
|
5
|
+
class Should
|
6
|
+
include Enumerize::Integrations::RSpec
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:klass) do
|
10
|
+
Class.new do
|
11
|
+
extend Enumerize
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:should) { Should.new }
|
16
|
+
let(:object) { klass.new }
|
17
|
+
|
18
|
+
describe '#matches?' do
|
19
|
+
before do
|
20
|
+
klass.enumerize(:sex, :in => [:male, :female])
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'returns true' do
|
24
|
+
matcher = should.enumerize(:sex).in(:male, :female)
|
25
|
+
matcher.matches?(object).must_equal true
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns false' do
|
29
|
+
matcher = should.enumerize(:sex).in(:bar)
|
30
|
+
matcher.matches?(object).must_equal false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#failure_message' do
|
35
|
+
before do
|
36
|
+
klass.enumerize(:sex, :in => [:male, :female], :default => :male)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'returns failure message for invalid :in option' do
|
40
|
+
matcher = should.enumerize(:sex).in(:bar)
|
41
|
+
matcher.subject = object
|
42
|
+
expected = ' expected :sex to allow value: "bar", but it allows "female", "male" instead'
|
43
|
+
matcher.failure_message.must_equal expected
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'returns failure message for invalid :with_default option' do
|
47
|
+
matcher = should.enumerize(:sex).in(:male, :female).with_default(:foo)
|
48
|
+
matcher.subject = object
|
49
|
+
expected = ' expected :sex to have "foo" as default value, but it sets "male" instead'
|
50
|
+
matcher.failure_message.must_equal expected
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/test/rspec_spec.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'enumerize'
|
2
|
+
require 'rspec'
|
3
|
+
|
4
|
+
class RSpecUser
|
5
|
+
extend Enumerize
|
6
|
+
|
7
|
+
enumerize :sex, in: [:male, :female], default: :male
|
8
|
+
end
|
9
|
+
|
10
|
+
describe RSpecUser do
|
11
|
+
it { should enumerize(:sex).in(:male, :female) }
|
12
|
+
it { should enumerize(:sex).in(:male, :female).with_default(:male) }
|
13
|
+
end
|
data/test/set_test.rb
CHANGED
@@ -109,4 +109,42 @@ describe Enumerize::Set do
|
|
109
109
|
set.join(', ').must_equal 'a, b'
|
110
110
|
end
|
111
111
|
end
|
112
|
+
|
113
|
+
describe 'boolean methods comparison' do
|
114
|
+
it 'returns true if value equals method' do
|
115
|
+
set << :a
|
116
|
+
set.a?.must_equal true
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'returns false if value does not equal method' do
|
120
|
+
set << :a
|
121
|
+
set.b?.must_equal false
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'raises NoMethodError if there are no values like boolean method' do
|
125
|
+
proc {
|
126
|
+
set.some_method?
|
127
|
+
}.must_raise NoMethodError
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'raises ArgumentError if arguments are passed' do
|
131
|
+
proc {
|
132
|
+
set.a?('<3')
|
133
|
+
}.must_raise ArgumentError
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'responds to methods for existing values' do
|
137
|
+
set.must_respond_to :a?
|
138
|
+
set.must_respond_to :b?
|
139
|
+
set.must_respond_to :c?
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'returns a method object' do
|
143
|
+
set.method(:a?).must_be_instance_of Method
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'does not respond to a method for not existing value' do
|
147
|
+
set.wont_respond_to :some_method?
|
148
|
+
end
|
149
|
+
end
|
112
150
|
end
|
data/test/simple_form_test.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -5,20 +5,6 @@ require 'active_model'
|
|
5
5
|
|
6
6
|
$VERBOSE=true
|
7
7
|
|
8
|
-
module SimpleForm
|
9
|
-
module Rails
|
10
|
-
def self.env
|
11
|
-
ActiveSupport::StringInquirer.new("test")
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
module Formtastic
|
17
|
-
module Rails
|
18
|
-
VERSION = ActiveSupport::VERSION
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
8
|
module RailsAdmin
|
23
9
|
end
|
24
10
|
|
data/test/value_test.rb
CHANGED
@@ -12,6 +12,34 @@ describe Enumerize::Value do
|
|
12
12
|
value.must_be :==, 'test_value'
|
13
13
|
end
|
14
14
|
|
15
|
+
describe 'translation' do
|
16
|
+
let(:attr) { Struct.new(:values, :name, :i18n_suffix).new([], "attribute_name", "model_name") }
|
17
|
+
|
18
|
+
it 'uses common translation' do
|
19
|
+
store_translations(:en, :enumerize => {:attribute_name => {:test_value => "Common translation"}}) do
|
20
|
+
value.text.must_be :==, "Common translation"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'uses model specific translation' do
|
25
|
+
store_translations(:en, :enumerize => {:model_name => {:attribute_name => {:test_value => "Model Specific translation"}}}) do
|
26
|
+
value.text.must_be :==, "Model Specific translation"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'uses model specific translation rather than common translation' do
|
31
|
+
store_translations(:en, :enumerize => {:attribute_name => {:test_value => "Common translation"}, :model_name => {:attribute_name => {:test_value => "Model Specific translation"}}}) do
|
32
|
+
value.text.must_be :==, "Model Specific translation"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'uses simply humanized value when translation is undefined' do
|
37
|
+
store_translations(:en, :enumerize => {}) do
|
38
|
+
value.text.must_be :==, "Test value"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
15
43
|
describe 'boolean methods comparison' do
|
16
44
|
before do
|
17
45
|
attr.values = [value, Enumerize::Value.new(attr, 'other_value')]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: enumerize
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-08-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -27,7 +27,8 @@ dependencies:
|
|
27
27
|
none: false
|
28
28
|
prerelease: false
|
29
29
|
name: activesupport
|
30
|
-
description: Enumerated attributes with I18n and ActiveRecord/Mongoid
|
30
|
+
description: Enumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper
|
31
|
+
support
|
31
32
|
email: team@brainspec.com
|
32
33
|
executables: []
|
33
34
|
extensions: []
|
@@ -51,8 +52,11 @@ files:
|
|
51
52
|
- lib/enumerize/hooks/formtastic.rb
|
52
53
|
- lib/enumerize/hooks/simple_form.rb
|
53
54
|
- lib/enumerize/integrations/rails_admin.rb
|
55
|
+
- lib/enumerize/integrations/rspec.rb
|
56
|
+
- lib/enumerize/integrations/rspec/matcher.rb
|
54
57
|
- lib/enumerize/module.rb
|
55
58
|
- lib/enumerize/module_attributes.rb
|
59
|
+
- lib/enumerize/predicatable.rb
|
56
60
|
- lib/enumerize/predicates.rb
|
57
61
|
- lib/enumerize/set.rb
|
58
62
|
- lib/enumerize/value.rb
|
@@ -63,10 +67,13 @@ files:
|
|
63
67
|
- test/base_test.rb
|
64
68
|
- test/formtastic_test.rb
|
65
69
|
- test/module_attributes_test.rb
|
70
|
+
- test/mongo_mapper_test.rb
|
66
71
|
- test/mongoid_test.rb
|
67
72
|
- test/multiple_test.rb
|
68
73
|
- test/predicates_test.rb
|
69
74
|
- test/rails_admin_test.rb
|
75
|
+
- test/rspec_matcher_test.rb
|
76
|
+
- test/rspec_spec.rb
|
70
77
|
- test/set_test.rb
|
71
78
|
- test/simple_form_test.rb
|
72
79
|
- test/support/mock_controller.rb
|
@@ -89,7 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
89
96
|
requirements:
|
90
97
|
- - ! '>='
|
91
98
|
- !ruby/object:Gem::Version
|
92
|
-
hash:
|
99
|
+
hash: 2859816307703102675
|
93
100
|
version: '0'
|
94
101
|
segments:
|
95
102
|
- 0
|
@@ -99,5 +106,5 @@ rubyforge_project:
|
|
99
106
|
rubygems_version: 1.8.23
|
100
107
|
signing_key:
|
101
108
|
specification_version: 3
|
102
|
-
summary: Enumerated attributes with I18n and ActiveRecord/Mongoid support
|
109
|
+
summary: Enumerated attributes with I18n and ActiveRecord/Mongoid/MongoMapper support
|
103
110
|
test_files: []
|