simple_enum 1.6.9 → 2.3.2
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 +4 -4
- data/.gitignore +1 -0
- data/Gemfile +9 -6
- data/LICENSE +1 -1
- data/README.md +331 -0
- data/Rakefile +9 -17
- data/lib/simple_enum/accessors/accessor.rb +61 -0
- data/lib/simple_enum/accessors/ignore_accessor.rb +11 -0
- data/lib/simple_enum/accessors/whiny_accessor.rb +12 -0
- data/lib/simple_enum/accessors.rb +28 -0
- data/lib/simple_enum/attribute.rb +109 -0
- data/lib/simple_enum/enum.rb +58 -0
- data/lib/simple_enum/hasher.rb +26 -0
- data/lib/simple_enum/mongoid.rb +16 -18
- data/lib/simple_enum/railtie.rb +17 -0
- data/lib/simple_enum/translation.rb +21 -0
- data/lib/simple_enum/version.rb +2 -2
- data/lib/simple_enum/view_helpers.rb +55 -0
- data/lib/simple_enum.rb +22 -278
- data/simple_enum.gemspec +9 -9
- data/spec/simple_enum/accessors_spec.rb +298 -0
- data/spec/simple_enum/attribute_spec.rb +272 -0
- data/spec/simple_enum/enum_spec.rb +136 -0
- data/spec/simple_enum/hasher_spec.rb +63 -0
- data/spec/simple_enum/mongoid_spec.rb +44 -0
- data/spec/simple_enum/translation_spec.rb +70 -0
- data/spec/simple_enum/view_helpers_spec.rb +71 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/support/active_record_support.rb +27 -0
- data/spec/support/i18n_support.rb +12 -0
- data/spec/support/model_support.rb +47 -0
- data/spec/support/mongoid_support.rb +47 -0
- metadata +55 -57
- data/README.rdoc +0 -293
- data/lib/simple_enum/enum_hash.rb +0 -64
- data/lib/simple_enum/validation.rb +0 -58
- data/locales/en.yml +0 -10
- data/test/array_conversions_test.rb +0 -21
- data/test/class_methods_test.rb +0 -114
- data/test/dirty_attributes_test.rb +0 -37
- data/test/enum_hash_test.rb +0 -73
- data/test/finders_test.rb +0 -45
- data/test/locales.yml +0 -25
- data/test/mongoid_test.rb +0 -66
- data/test/object_backed_test.rb +0 -61
- data/test/orm/active_record.rb +0 -114
- data/test/orm/common.rb +0 -23
- data/test/orm/mongoid.rb +0 -114
- data/test/poro_test.rb +0 -20
- data/test/prefixes_test.rb +0 -36
- data/test/simple_enum_test.rb +0 -314
- data/test/test_helper.rb +0 -40
- data/test/without_shortcuts_test.rb +0 -39
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'active_support/core_ext/string'
|
2
|
+
|
3
|
+
module SimpleEnum
|
4
|
+
class Enum
|
5
|
+
attr_reader :name, :hash
|
6
|
+
|
7
|
+
def initialize(name, hash)
|
8
|
+
@name = name.to_s
|
9
|
+
@hash = hash
|
10
|
+
end
|
11
|
+
|
12
|
+
def include?(key)
|
13
|
+
hash.key?(key.to_s) || hash.value?(key)
|
14
|
+
end
|
15
|
+
|
16
|
+
def key(value)
|
17
|
+
key = hash.key(value)
|
18
|
+
key.to_sym if key
|
19
|
+
end
|
20
|
+
|
21
|
+
def value(key)
|
22
|
+
value = hash[key.to_s]
|
23
|
+
value = key if hash.value?(key)
|
24
|
+
value
|
25
|
+
end
|
26
|
+
alias_method :[], :value
|
27
|
+
|
28
|
+
def fetch(key)
|
29
|
+
value(key) || raise("Key \"#{key}\" not found")
|
30
|
+
end
|
31
|
+
|
32
|
+
def each_pair(&block)
|
33
|
+
hash.each_pair(&block)
|
34
|
+
end
|
35
|
+
alias_method :each, :each_pair
|
36
|
+
|
37
|
+
def map(&block)
|
38
|
+
hash.map(&block)
|
39
|
+
end
|
40
|
+
|
41
|
+
def keys
|
42
|
+
hash.keys
|
43
|
+
end
|
44
|
+
|
45
|
+
def values
|
46
|
+
hash.values
|
47
|
+
end
|
48
|
+
|
49
|
+
def values_at(*keys)
|
50
|
+
keys = keys.map(&:to_s)
|
51
|
+
hash.values_at(*keys)
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_s
|
55
|
+
name
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SimpleEnum
|
2
|
+
module Hasher
|
3
|
+
DefaultHasher = ->(values) {
|
4
|
+
Hash.new.tap do |enum_hash|
|
5
|
+
pairs = values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index
|
6
|
+
pairs.each { |name, value| enum_hash[name.to_s] = value }
|
7
|
+
end
|
8
|
+
}
|
9
|
+
|
10
|
+
StringHasher = ->(values) {
|
11
|
+
Hash.new.tap do |enum_hash|
|
12
|
+
values.each { |name, *args| enum_hash[name.to_s] = name.to_s }
|
13
|
+
end
|
14
|
+
}
|
15
|
+
|
16
|
+
HASHERS = {
|
17
|
+
string: StringHasher
|
18
|
+
}
|
19
|
+
|
20
|
+
def self.map(values, options = {})
|
21
|
+
mapper = options.fetch(:map, SimpleEnum.builder)
|
22
|
+
mapper = HASHERS[mapper] || DefaultHasher unless mapper.respond_to?(:call)
|
23
|
+
mapper.call(values).freeze
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/simple_enum/mongoid.rb
CHANGED
@@ -15,37 +15,35 @@ module SimpleEnum
|
|
15
15
|
#
|
16
16
|
# When no field is requested:
|
17
17
|
#
|
18
|
-
# field :gender_cd, :
|
19
|
-
# as_enum :gender, [:female, :male], :
|
18
|
+
# field :gender_cd, type: Integer
|
19
|
+
# as_enum :gender, [:female, :male], field: false
|
20
20
|
#
|
21
21
|
# or custom field options (like e.g. type want to be passed):
|
22
22
|
#
|
23
|
-
# as_enum :gender, [:female, :male], :
|
23
|
+
# as_enum :gender, [:female, :male], field: { type: Integer }
|
24
24
|
#
|
25
25
|
module Mongoid
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
class_attribute :simple_enum_definitions, :instance_writer => false, :instance_reader => false
|
26
|
+
def self.included(base)
|
27
|
+
base.extend SimpleEnum::Attribute
|
28
|
+
base.extend SimpleEnum::Translation
|
29
|
+
base.extend SimpleEnum::Mongoid::ClassMethods
|
31
30
|
end
|
32
31
|
|
33
32
|
module ClassMethods
|
34
|
-
include SimpleEnum::ClassMethods
|
35
|
-
|
36
33
|
# Wrap method chain to create mongoid field and additional
|
37
34
|
# column options
|
38
|
-
def
|
39
|
-
options = SimpleEnum.default_options.merge({ :column => "#{enum_cd}_cd" }).deep_merge(options)
|
40
|
-
|
41
|
-
# forward custom field options
|
35
|
+
def as_enum(name, values, options = {})
|
42
36
|
field_options = options.delete(:field)
|
43
|
-
|
37
|
+
enum = super
|
38
|
+
accessor = send("#{name.to_s.pluralize}_accessor")
|
39
|
+
|
40
|
+
unless field_options === false
|
41
|
+
field_options ||= SimpleEnum.field
|
42
|
+
field(accessor.source, field_options) if field_options
|
43
|
+
end
|
44
44
|
|
45
|
-
|
46
|
-
as_enum_without_mongoid(enum_cd, values, options)
|
45
|
+
enum
|
47
46
|
end
|
48
|
-
alias_method_chain :as_enum, :mongoid
|
49
47
|
end
|
50
48
|
end
|
51
49
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'simple_enum'
|
2
|
+
|
3
|
+
module SimpleEnum
|
4
|
+
class Railtie < Rails::Railtie
|
5
|
+
|
6
|
+
initializer 'simple_enum.extend_active_record' do
|
7
|
+
ActiveSupport.on_load(:active_record) do
|
8
|
+
ActiveRecord::Base.send :extend, SimpleEnum::Attribute
|
9
|
+
ActiveRecord::Base.send :extend, SimpleEnum::Translation
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
initializer 'simple_enum.view_helpers' do
|
14
|
+
ActionView::Base.send :include, SimpleEnum::ViewHelpers
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'i18n'
|
2
|
+
|
3
|
+
module SimpleEnum
|
4
|
+
module Translation
|
5
|
+
def human_enum_name(enum, key, options = {})
|
6
|
+
return '' unless key.present?
|
7
|
+
|
8
|
+
defaults = lookup_ancestors.map do |klass|
|
9
|
+
:"#{self.i18n_scope}.enums.#{klass.model_name.i18n_key}.#{enum}.#{key}"
|
10
|
+
end
|
11
|
+
|
12
|
+
defaults << :"enums.#{self.model_name.i18n_key}.#{enum}.#{key}"
|
13
|
+
defaults << :"enums.#{enum}.#{key}"
|
14
|
+
defaults << options.delete(:default) if options[:default]
|
15
|
+
defaults << key.to_s.humanize
|
16
|
+
|
17
|
+
options.reverse_merge! count: 1, default: defaults
|
18
|
+
I18n.translate(defaults.shift, options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/simple_enum/version.rb
CHANGED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'i18n'
|
2
|
+
|
3
|
+
module SimpleEnum
|
4
|
+
module ViewHelpers
|
5
|
+
|
6
|
+
# A helper to build forms with Rails' form builder, built to be used with
|
7
|
+
# f.select helper.
|
8
|
+
#
|
9
|
+
# f.select :gender, enum_option_pairs(User, :gender), ...
|
10
|
+
#
|
11
|
+
# record - The model or Class with the enum
|
12
|
+
# enum - The Symbol with the name of the enum to create the options for
|
13
|
+
# encode_as_value - The Boolean which defines if either the key or the value
|
14
|
+
# should be used as value attribute for the option,
|
15
|
+
# defaults to using the key (i.e. false)
|
16
|
+
#
|
17
|
+
# FIXME: check if the name `enum_option_pairs` is actually good and clear
|
18
|
+
# enough...
|
19
|
+
#
|
20
|
+
# Returns an Array of pairs, like e.g. `[["Translated key", "key"], ...]`
|
21
|
+
def enum_option_pairs(record, enum, encode_as_value = false)
|
22
|
+
reader = enum.to_s.pluralize
|
23
|
+
record = record.class unless record.respond_to?(reader)
|
24
|
+
|
25
|
+
record.send(reader).map { |key, value|
|
26
|
+
name = record.human_enum_name(enum, key) if record.respond_to?(:human_enum_name)
|
27
|
+
name ||= translate_enum_key(enum, key)
|
28
|
+
[name, encode_as_value ? value : key]
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
# Helper method to return the translated value of an enum.
|
33
|
+
#
|
34
|
+
# translate_enum(user, :gender) # => "Frau"
|
35
|
+
#
|
36
|
+
# Has been aliased to `te` as a convenience method as well.
|
37
|
+
#
|
38
|
+
# record - The model instance holding the enum
|
39
|
+
# key - The Symbol with the name of the enum, i.e. same key as used in the
|
40
|
+
# `as_enum` call
|
41
|
+
#
|
42
|
+
# Returns String with translation of enum
|
43
|
+
def translate_enum(record, key)
|
44
|
+
record.class.human_enum_name(key, record.public_send(key))
|
45
|
+
end
|
46
|
+
alias_method :te, :translate_enum
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def translate_enum_key(enum, key)
|
51
|
+
defaults = [:"enums.#{enum}.#{key}", key.to_s.humanize]
|
52
|
+
I18n.translate defaults.shift, default: defaults, count: 1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/simple_enum.rb
CHANGED
@@ -3,299 +3,43 @@
|
|
3
3
|
# but instead on integer columns.
|
4
4
|
#
|
5
5
|
# Author:: Lukas Westermann
|
6
|
-
# Copyright:: Copyright (c) 2009 Lukas Westermann (Zurich, Switzerland)
|
7
|
-
#
|
6
|
+
# Copyright:: Copyright (c) 2009-2014 Lukas Westermann (Zurich, Switzerland)
|
7
|
+
# License:: MIT-Licence (http://www.opensource.org/licenses/mit-license.php)
|
8
8
|
#
|
9
9
|
# See the +as_enum+ documentation for more details.
|
10
10
|
|
11
|
-
# because we depend on i18n and activesupport
|
12
|
-
require 'i18n'
|
13
11
|
require 'active_support'
|
14
12
|
|
15
|
-
require 'simple_enum/
|
16
|
-
require 'simple_enum/
|
17
|
-
|
18
|
-
require '
|
13
|
+
require 'simple_enum/version'
|
14
|
+
require 'simple_enum/attribute'
|
15
|
+
require 'simple_enum/translation'
|
16
|
+
require 'simple_enum/view_helpers'
|
19
17
|
|
20
18
|
# Base module which gets included in <tt>ActiveRecord::Base</tt>. See documentation
|
21
19
|
# of +SimpleEnum::ClassMethods+ for more details.
|
22
20
|
module SimpleEnum
|
21
|
+
mattr_accessor :with
|
22
|
+
@@with = [:attribute, :dirty, :scope]
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
# Provides configurability to SimpleEnum, allows to override some defaults which are
|
27
|
-
# defined for all uses of +as_enum+. Most options from +as_enum+ are available, such as:
|
28
|
-
# * <tt>:prefix</tt> - Define a prefix, which is prefixed to the shortcut methods (e.g. <tt><symbol>!</tt> and
|
29
|
-
# <tt><symbol>?</tt>), if it's set to <tt>true</tt> the enumeration name is used as a prefix, else a custom
|
30
|
-
# prefix (symbol or string) (default is <tt>nil</tt> => no prefix)
|
31
|
-
# * <tt>:slim</tt> - If set to <tt>true</tt> no shortcut methods for all enumeration values are being generated, if
|
32
|
-
# set to <tt>:class</tt> only class-level shortcut methods are disabled (default is <tt>nil</tt> => they are generated)
|
33
|
-
# * <tt>:upcase</tt> - If set to +true+ the <tt>Klass.foos</tt> is named <tt>Klass.FOOS</tt>, why? To better suite some
|
34
|
-
# coding-styles (default is +false+ => downcase)
|
35
|
-
# * <tt>:whiny</tt> - Boolean value which if set to <tt>true</tt> will throw an <tt>ArgumentError</tt>
|
36
|
-
# if an invalid value is passed to the setter (e.g. a value for which no enumeration exists). if set to
|
37
|
-
# <tt>false</tt> no exception is thrown and the internal value is set to <tt>nil</tt> (default is <tt>true</tt>)
|
38
|
-
# * <tt>:dirty</tt> - Boolean value which if set to <tt>true</tt> generates <tt>..._was</tt> and <tt>..._changed?</tt>
|
39
|
-
# methods for the enum, which delegate to the internal column.
|
40
|
-
# * <tt>:strings</tt> - Boolean value which if set to <tt>true</tt> defaults array values as strings instead of integers.
|
41
|
-
def default_options
|
42
|
-
@default_options ||= {
|
43
|
-
:whiny => true,
|
44
|
-
:upcase => false
|
45
|
-
}
|
46
|
-
end
|
47
|
-
|
48
|
-
def included(base) #:nodoc:
|
49
|
-
base.send :class_attribute, :simple_enum_definitions, :instance_writer => false, :instance_reader => false
|
50
|
-
base.send :extend, ClassMethods
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
module ClassMethods
|
55
|
-
|
56
|
-
# Provides ability to create simple enumerations based on hashes or arrays, backed
|
57
|
-
# by integer columns (but not limited to integer columns).
|
58
|
-
#
|
59
|
-
# Columns are supposed to be suffixed by <tt>_cd</tt>, if not, use <tt>:column => 'the_column_name'</tt>,
|
60
|
-
# so some example migrations:
|
61
|
-
#
|
62
|
-
# add_column :users, :gender_cd, :integer
|
63
|
-
# add_column :users, :status, :integer # and a custom column...
|
64
|
-
#
|
65
|
-
# and then in your model:
|
66
|
-
#
|
67
|
-
# class User < ActiveRecord::Base
|
68
|
-
# as_enum :gender, [:male, :female]
|
69
|
-
# end
|
70
|
-
#
|
71
|
-
# # or use a hash:
|
72
|
-
#
|
73
|
-
# class User < ActiveRecord::Base
|
74
|
-
# as_enum :user_status, { :active => 1, :inactive => 0, :archived => 2, :deleted => 3 }, :column => 'status'
|
75
|
-
# end
|
76
|
-
#
|
77
|
-
# Now it's possible to access the enumeration and the internally stored value like:
|
78
|
-
#
|
79
|
-
# john_doe = User.new
|
80
|
-
# john_doe.gender # => nil
|
81
|
-
# john_doe.gender = :male
|
82
|
-
# john_doe.gender # => :male
|
83
|
-
# john_doe.gender_cd # => 0
|
84
|
-
#
|
85
|
-
# And to make life a tad easier: a few shortcut methods to work with the enumeration are also created.
|
86
|
-
#
|
87
|
-
# john_doe.male? # => true
|
88
|
-
# john_doe.female? # => false
|
89
|
-
# john_doe.female! # => :female (set's gender to :female => gender_cd = 1)
|
90
|
-
# john_doe.male? # => false
|
91
|
-
#
|
92
|
-
# Sometimes it's required to access the db-backed values, like e.g. in a query:
|
93
|
-
#
|
94
|
-
# User.genders # => { :male => 0, :female => 1}, values hash
|
95
|
-
# User.genders(:male) # => 0, value access (via hash)
|
96
|
-
# User.female # => 1, direct access
|
97
|
-
# User.find :all, :conditions => { :gender_cd => User.female } # => [...], list with all women
|
98
|
-
#
|
99
|
-
# To access the key/value assocations in a helper like the select helper or similar use:
|
100
|
-
#
|
101
|
-
# <%= select(:user, :gender, User.genders.keys)
|
102
|
-
#
|
103
|
-
# The generated shortcut methods (like <tt>male?</tt> or <tt>female!</tt> etc.) can also be prefixed
|
104
|
-
# using the <tt>:prefix</tt> option. If the value is <tt>true</tt>, the shortcut methods are prefixed
|
105
|
-
# with the name of the enumeration.
|
106
|
-
#
|
107
|
-
# class User < ActiveRecord::Base
|
108
|
-
# as_enum :gender, [:male, :female], :prefix => true
|
109
|
-
# end
|
110
|
-
#
|
111
|
-
# jane_doe = User.new
|
112
|
-
# jane_doe.gender = :female # this is still as-is
|
113
|
-
# jane_doe.gender_cd # => 1, and so it this
|
114
|
-
#
|
115
|
-
# jane_doe.gender_female? # => true (instead of jane_doe.female?)
|
116
|
-
#
|
117
|
-
# It is also possible to supply a custom prefix.
|
118
|
-
#
|
119
|
-
# class Item < ActiveRecord::Base
|
120
|
-
# as_enum :status, [:inactive, :active, :deleted], :prefix => :state
|
121
|
-
# end
|
122
|
-
#
|
123
|
-
# item = Item.new(:status => :active)
|
124
|
-
# item.state_inactive? # => false
|
125
|
-
# Item.state_deleted # => 2
|
126
|
-
# Item.status(:deleted) # => 2, same as above...
|
127
|
-
#
|
128
|
-
# To disable the generation of the shortcut methods for all enumeration values, add <tt>:slim => true</tt> to
|
129
|
-
# the options.
|
130
|
-
#
|
131
|
-
# class Address < ActiveRecord::Base
|
132
|
-
# as_enum :canton, {:aargau => 'ag', ..., :wallis => 'vs', :zug => 'zg', :zurich => 'zh'}, :slim => true
|
133
|
-
# end
|
134
|
-
#
|
135
|
-
# home = Address.new(:canton => :zurich, :street => 'Bahnhofstrasse 1', ...)
|
136
|
-
# home.canton # => :zurich
|
137
|
-
# home.canton_cd # => 'zh'
|
138
|
-
# home.aargau! # throws NoMethodError: undefined method `aargau!'
|
139
|
-
# Address.aargau # throws NoMethodError: undefined method `aargau`
|
140
|
-
#
|
141
|
-
# This is especially useful if there are (too) many enumeration values, or these shortcut methods
|
142
|
-
# are not required.
|
143
|
-
#
|
144
|
-
# === Configuration options:
|
145
|
-
# * <tt>:column</tt> - Specifies a custom column name, instead of the default suffixed <tt>_cd</tt> column
|
146
|
-
# * <tt>:prefix</tt> - Define a prefix, which is prefixed to the shortcut methods (e.g. <tt><symbol>!</tt> and
|
147
|
-
# <tt><symbol>?</tt>), if it's set to <tt>true</tt> the enumeration name is used as a prefix, else a custom
|
148
|
-
# prefix (symbol or string) (default is <tt>nil</tt> => no prefix)
|
149
|
-
# * <tt>:slim</tt> - If set to <tt>true</tt> no shortcut methods for all enumeration values are being generated, if
|
150
|
-
# set to <tt>:class</tt> only class-level shortcut methods are disabled (default is <tt>nil</tt> => they are generated)
|
151
|
-
# * <tt>:upcase</tt> - If set to +true+ the <tt>Klass.foos</tt> is named <tt>Klass.FOOS</tt>, why? To better suite some
|
152
|
-
# coding-styles (default is +false+ => downcase)
|
153
|
-
# * <tt>:whiny</tt> - Boolean value which if set to <tt>true</tt> will throw an <tt>ArgumentError</tt>
|
154
|
-
# if an invalid value is passed to the setter (e.g. a value for which no enumeration exists). if set to
|
155
|
-
# <tt>false</tt> no exception is thrown and the internal value is set to <tt>nil</tt> (default is <tt>true</tt>)
|
156
|
-
# * <tt>:dirty</tt> - Boolean value which if set to <tt>true</tt> generates <tt>..._was</tt> and <tt>..._changed?</tt>
|
157
|
-
# methods for the enum, which delegate to the internal column (default is <tt>false</tt>)
|
158
|
-
# * <tt>:strings</tt> - Boolean value which if set to <tt>true</tt> stores array values as strings instead of it's index.
|
159
|
-
# * <tt>:field</tt> - Also allowed as valid key, for Mongoid integration + default options, see simple_enum#27.
|
160
|
-
#
|
161
|
-
def as_enum(enum_cd, values, options = {})
|
162
|
-
options = SimpleEnum.default_options.merge({ :column => "#{enum_cd}_cd" }).merge(options)
|
163
|
-
options.assert_valid_keys(:column, :whiny, :prefix, :slim, :upcase, :dirty, :strings, :field)
|
164
|
-
|
165
|
-
metaclass = (class << self; self; end)
|
166
|
-
|
167
|
-
# convert array to hash
|
168
|
-
values = SimpleEnum::EnumHash.new(values, options[:strings])
|
169
|
-
values_inverted = values.invert
|
170
|
-
|
171
|
-
# store info away
|
172
|
-
self.enum_definitions[enum_cd] = self.enum_definitions[options[:column]] = { :name => enum_cd, :column => options[:column], :options => options }
|
173
|
-
|
174
|
-
# raise error if enum_cd == column
|
175
|
-
raise ArgumentError, "[simple_enum] use different names for #{enum_cd}'s name and column name." if enum_cd.to_s == options[:column].to_s
|
176
|
-
|
177
|
-
# generate getter
|
178
|
-
define_method("#{enum_cd}") do
|
179
|
-
id = send(options[:column])
|
180
|
-
values_inverted[id]
|
181
|
-
end
|
182
|
-
|
183
|
-
# generate setter
|
184
|
-
define_method("#{enum_cd}=") do |new_value|
|
185
|
-
return send("#{options[:column]}=", nil) if new_value.blank?
|
186
|
-
|
187
|
-
new_value = new_value.to_s if options[:strings]
|
188
|
-
real = nil
|
189
|
-
if values.contains?(new_value)
|
190
|
-
real = values[EnumHash.symbolize(new_value)]
|
191
|
-
real = new_value if real.nil? && values_inverted[new_value].present?
|
192
|
-
end
|
193
|
-
|
194
|
-
raise ArgumentError, "Invalid enumeration value: #{new_value}" if options[:whiny] && !real
|
195
|
-
send("#{options[:column]}=", real)
|
196
|
-
end
|
197
|
-
|
198
|
-
# generate checker
|
199
|
-
define_method("#{enum_cd}?") do |*args|
|
200
|
-
current = send(enum_cd)
|
201
|
-
return current.to_s == args.first.to_s if args.length > 0
|
24
|
+
mattr_accessor :accessor
|
25
|
+
@@accessor = :default
|
202
26
|
|
203
|
-
|
204
|
-
|
27
|
+
mattr_accessor :builder
|
28
|
+
@@builder = :default
|
205
29
|
|
206
|
-
|
207
|
-
|
208
|
-
define_method("#{enum_cd}_changed?") do
|
209
|
-
self.send("#{options[:column]}_changed?")
|
210
|
-
end
|
30
|
+
mattr_accessor :suffix
|
31
|
+
@@suffix = "_cd"
|
211
32
|
|
212
|
-
|
213
|
-
|
214
|
-
end
|
215
|
-
end
|
33
|
+
mattr_accessor :field
|
34
|
+
@@field = {}
|
216
35
|
|
217
|
-
|
218
|
-
|
219
|
-
enum_attr = :"#{attr_name.downcase}_enum_hash"
|
36
|
+
mattr_accessor :pluralize_scopes
|
37
|
+
@@pluralize_scopes = true
|
220
38
|
|
221
|
-
|
222
|
-
|
223
|
-
end
|
224
|
-
|
225
|
-
# generate find_by enum singleton
|
226
|
-
(class << self; self end).send(:define_method, "find_by_#{enum_cd}") do |*args|
|
227
|
-
send("find_by_#{options[:column]}", args)
|
228
|
-
end
|
229
|
-
|
230
|
-
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
231
|
-
class_attribute #{enum_attr.inspect}, :instance_writer => false, :instance_reader => false
|
232
|
-
|
233
|
-
def self.#{attr_name}(*args)
|
234
|
-
return #{enum_attr} if args.first.nil?
|
235
|
-
return #{enum_attr}[args.first] if args.size == 1
|
236
|
-
args.inject([]) { |ary, sym| ary << #{enum_attr}[sym]; ary }
|
237
|
-
end
|
238
|
-
|
239
|
-
def self.#{attr_name}_for_select(attr = :key, &block)
|
240
|
-
self.#{attr_name}.map do |k,v|
|
241
|
-
[block_given? ? yield(k,v) : self.human_enum_name(#{attr_name.inspect}, k), attr == :value ? v : k]
|
242
|
-
end
|
243
|
-
end
|
244
|
-
RUBY
|
245
|
-
|
246
|
-
# write values
|
247
|
-
self.send "#{enum_attr}=", values
|
248
|
-
|
249
|
-
# only create if :slim is not defined
|
250
|
-
if options[:slim] != true
|
251
|
-
# create both, boolean operations and *bang* operations for each
|
252
|
-
# enum "value"
|
253
|
-
prefix = options[:prefix] && "#{options[:prefix] == true ? enum_cd : options[:prefix]}_"
|
254
|
-
|
255
|
-
values.each do |k,code|
|
256
|
-
sym = EnumHash.symbolize(k)
|
257
|
-
|
258
|
-
define_method("#{prefix}#{sym}?") do
|
259
|
-
current = send(options[:column])
|
260
|
-
code == current
|
261
|
-
end
|
262
|
-
define_method("#{prefix}#{sym}!") do
|
263
|
-
send("#{options[:column]}=", code)
|
264
|
-
sym
|
265
|
-
end
|
266
|
-
|
267
|
-
# allow class access to each value
|
268
|
-
unless options[:slim] === :class
|
269
|
-
metaclass.send(:define_method, "#{prefix}#{sym}", Proc.new { |*args| args.first ? k : code })
|
270
|
-
end
|
271
|
-
end
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
def human_enum_name(enum, key, options = {})
|
276
|
-
defaults = lookup_ancestors.map do |klass|
|
277
|
-
:"#{self.i18n_scope}.enums.#{klass.model_name.i18n_key}.#{enum}.#{key}"
|
278
|
-
end
|
279
|
-
|
280
|
-
defaults << :"enums.#{self.model_name.i18n_key}.#{enum}.#{key}"
|
281
|
-
defaults << :"enums.#{enum}.#{key}"
|
282
|
-
defaults << options.delete(:default) if options[:default]
|
283
|
-
defaults << key.to_s.humanize
|
284
|
-
|
285
|
-
options.reverse_merge! :count => 1, :default => defaults
|
286
|
-
I18n.translate(defaults.shift, options)
|
287
|
-
end
|
288
|
-
|
289
|
-
def enum_definitions
|
290
|
-
self.simple_enum_definitions ||= {}
|
291
|
-
end
|
39
|
+
def self.configure
|
40
|
+
yield(self)
|
292
41
|
end
|
293
42
|
end
|
294
43
|
|
295
|
-
#
|
296
|
-
|
297
|
-
ActiveRecord::Base.send(:include, SimpleEnum)
|
298
|
-
end
|
299
|
-
|
300
|
-
# setup i18n load path...
|
301
|
-
I18n.load_path << File.join(File.dirname(__FILE__), '..', 'locales', 'en.yml')
|
44
|
+
# Load rails support
|
45
|
+
require 'simple_enum/railtie' if defined?(Rails)
|
data/simple_enum.gemspec
CHANGED
@@ -8,23 +8,23 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.summary = "Simple enum-like field support for models."
|
9
9
|
s.description = "Provides enum-like fields for ActiveRecord, ActiveModel and Mongoid models."
|
10
10
|
|
11
|
-
s.required_ruby_version = ">= 1.
|
12
|
-
s.required_rubygems_version = ">=
|
11
|
+
s.required_ruby_version = ">= 1.9.3"
|
12
|
+
s.required_rubygems_version = ">= 2.0.0"
|
13
13
|
|
14
14
|
s.authors = ["Lukas Westermann"]
|
15
15
|
s.email = ["lukas.westermann@gmail.com"]
|
16
16
|
s.homepage = "http://lwe.github.com/simple_enum/"
|
17
17
|
|
18
|
-
s.files = %w{.gitignore Rakefile Gemfile README.
|
19
|
-
s.test_files = s.files.grep(%r{^(test|spec
|
18
|
+
s.files = %w{.gitignore Rakefile Gemfile README.md LICENSE simple_enum.gemspec} + Dir['**/*.{rb,yml}']
|
19
|
+
s.test_files = s.files.grep(%r{^(test|spec)/})
|
20
20
|
s.require_paths = %w{lib}
|
21
21
|
|
22
22
|
s.license = 'MIT'
|
23
23
|
|
24
|
-
s.add_dependency
|
24
|
+
s.add_dependency 'activesupport', '>= 4.0.0'
|
25
25
|
|
26
|
-
s.add_development_dependency 'rake', '>=
|
27
|
-
s.add_development_dependency '
|
28
|
-
s.add_development_dependency '
|
29
|
-
s.add_development_dependency '
|
26
|
+
s.add_development_dependency 'rake', '>= 10.1.0'
|
27
|
+
s.add_development_dependency 'activerecord', '>= 4.0.0'
|
28
|
+
s.add_development_dependency 'mongoid', '>= 4.0.0'
|
29
|
+
s.add_development_dependency 'rspec', '~> 2.14'
|
30
30
|
end
|