enumerated 1.0.1
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.
- data/.gitignore +6 -0
- data/.rspec +1 -0
- data/.rvmrc +4 -0
- data/Gemfile +4 -0
- data/README.md +148 -0
- data/Rakefile +2 -0
- data/enumerator.gemspec +27 -0
- data/lib/enumerated.rb +93 -0
- data/lib/enumerated/definition.rb +68 -0
- data/lib/enumerated/version.rb +3 -0
- data/spec/dog_spec.rb +38 -0
- data/spec/fixtures/helpers.rb +3 -0
- data/spec/fixtures/models.rb +13 -0
- data/spec/hairs_helper_spec.rb +33 -0
- data/spec/locales/en.yml +8 -0
- data/spec/matchers.rb +11 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/user_spec.rb +245 -0
- data/spec/users_helper_spec.rb +33 -0
- metadata +151 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/.rvmrc
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
# Enumerated - yet another enumeration gem for ActiveRecord
|
2
|
+
|
3
|
+
Ok, there are few gems that provides enumeration support to Rails ActiveRecord models, but still missing some
|
4
|
+
features. The goal of the **Enumerated** gem is not to provide the feature richest enumeration support, but to make it
|
5
|
+
useful to use together with selection/drop down lists. So if you need advanced support consider usage of other
|
6
|
+
gem, however if you simply need to work with selection lists this gem is for you.
|
7
|
+
|
8
|
+
The **Enumerated** gem will provide support to translate enumerated attributes into labels that are shown in
|
9
|
+
selection lists on view and into keys which are stored in the database. This decouples the values stored in
|
10
|
+
database and those presented to user on view, so you can freely change labels and no database changes are
|
11
|
+
required. **I18n** is supported by default.
|
12
|
+
|
13
|
+
The enumerated attribute keys are stored in database as strings. If you want to modify enumeration's key simply
|
14
|
+
write the migration that will rename appropriate rows. Changing the label doesn't require any modifications
|
15
|
+
in database.
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
Add to your Gemfile:
|
20
|
+
|
21
|
+
gem 'enumerated'
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
First you need to define your attributes that will be enumerated:
|
26
|
+
|
27
|
+
create_table :users do |t|
|
28
|
+
t.string :gender
|
29
|
+
end
|
30
|
+
|
31
|
+
Next you need to define your enumerations in the model class:
|
32
|
+
|
33
|
+
class User < ActiveRecord::Base
|
34
|
+
enumerated :gender, [ :male, :female ]
|
35
|
+
end
|
36
|
+
|
37
|
+
Enumerated attributes are the values that will be stored in the database (as string).
|
38
|
+
|
39
|
+
Having declared enumeration you gain access to several methods. At first you can list
|
40
|
+
all available enumeration values:
|
41
|
+
|
42
|
+
User.genders # => [["Male", :male], ["Female", :female]]
|
43
|
+
|
44
|
+
Views and controllers will also have access to helper method:
|
45
|
+
|
46
|
+
user_genders # => [["Male", :male], ["Female", :female]]
|
47
|
+
|
48
|
+
By default this helper method will be added to the controller corresponding to the model,
|
49
|
+
so in case of ``User`` model the ``user_genders`` method will be added to ``UsersHelper``.
|
50
|
+
If you want to declare other module use ``:helper`` parameter in the declaration:
|
51
|
+
|
52
|
+
class User < ActiveRecord::Base
|
53
|
+
enumerated :gender, [ :male, :female ], :helper => ApplicationHelper
|
54
|
+
end
|
55
|
+
|
56
|
+
If you do not want the helper method at all use:
|
57
|
+
|
58
|
+
class User < ActiveRecord::Base
|
59
|
+
enumerated :gender, [ :male, :female ], :helper => false
|
60
|
+
end
|
61
|
+
|
62
|
+
### Applying and reading enumeration
|
63
|
+
|
64
|
+
There are several ways to set and get the value of enumerated attribute:
|
65
|
+
|
66
|
+
user = User.new
|
67
|
+
user.gender = :male
|
68
|
+
user.gender # => :male
|
69
|
+
user.male? # => true
|
70
|
+
user.female? # => false
|
71
|
+
user.gender_label # => "Male"
|
72
|
+
user.female! # => :female
|
73
|
+
user.gender_label # => "Female"
|
74
|
+
|
75
|
+
### Labels and I18n
|
76
|
+
|
77
|
+
Enumeration labels may be defined in two ways. First is the place where the enumeration is
|
78
|
+
declared:
|
79
|
+
|
80
|
+
class User < ActiveRecord::Base
|
81
|
+
enumerated :gender, { :male => "Sir", :female => "Madam" }
|
82
|
+
end
|
83
|
+
|
84
|
+
Second, and more preferred way is the localization file:
|
85
|
+
|
86
|
+
en:
|
87
|
+
activerecord:
|
88
|
+
enumerations:
|
89
|
+
user:
|
90
|
+
gender:
|
91
|
+
male: "Sir"
|
92
|
+
female: "Madam"
|
93
|
+
|
94
|
+
If labels are not explicitly defined the humanized versions are taken by default. Labels defined
|
95
|
+
in ``Hash`` will override those defined in localization file.
|
96
|
+
|
97
|
+
## Advanced usage
|
98
|
+
|
99
|
+
By default the order of enumeration options returned by the helper methods is unspecified (albeit most probably
|
100
|
+
it will match the order of declaration). If you need to define certain order of the labels (eg. on selection list)
|
101
|
+
use the ``:order`` parameter:
|
102
|
+
|
103
|
+
User.genders :order => [ :female, :male ] # => [["Female", :female], ["Male", :male]]
|
104
|
+
user_genders :order => [ :female, :male ] # => [["Female", :female], ["Male", :male]]
|
105
|
+
|
106
|
+
You can also provide alphabetical order:
|
107
|
+
|
108
|
+
User.genders :order => :alphabetical # => [["Female", :female], ["Male", :male]]
|
109
|
+
|
110
|
+
Also you can define which enumeration options you want to method return:
|
111
|
+
|
112
|
+
User.genders :except => [:male] # => [["Female", :female]]
|
113
|
+
User.genders :only => [:female] # => [["Female", :female]]
|
114
|
+
|
115
|
+
Labels might be overridden:
|
116
|
+
|
117
|
+
User.genders :override => { :male => "Sir" } # => [["Sir", :male], ["Female", :female]]
|
118
|
+
|
119
|
+
*Note that all parameters shown in this section also applies to method defined in helper module.*
|
120
|
+
|
121
|
+
## Validation
|
122
|
+
|
123
|
+
By default the ``enumerated`` declaration will add the validation for inclusion of the values specified
|
124
|
+
in the declaration. It means that by default model won't be valid if enumerated attribute will have value
|
125
|
+
other than specified in the ``enumerated`` declaration:
|
126
|
+
|
127
|
+
class User < ActiveRecord::Base
|
128
|
+
enumerated :gender, [:male, :female]
|
129
|
+
# Implicitly adds the following:
|
130
|
+
validates :gender, :inclusion => [nil, '', :male, :female]
|
131
|
+
end
|
132
|
+
|
133
|
+
If you want to prevent **Enumerated** gem adding the validation type:
|
134
|
+
|
135
|
+
class User < ActiveRecord::Base
|
136
|
+
enumerated :gender, [:male, :female], :validate => false
|
137
|
+
end
|
138
|
+
|
139
|
+
By default **Enumerated** will add ``nil`` value to the array of expected values (in inclusion statement).
|
140
|
+
If you do not want to include ``nil`` type:
|
141
|
+
|
142
|
+
class User < ActiveRecord::Base
|
143
|
+
enumerated :gender, [:male, :female], :nillable => false
|
144
|
+
end
|
145
|
+
|
146
|
+
## Issues
|
147
|
+
|
148
|
+
* Currently not supporting STI
|
data/Rakefile
ADDED
data/enumerator.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "enumerated/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "enumerated"
|
7
|
+
s.version = Enumerated::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Michal Orman"]
|
10
|
+
s.email = ["michal.orman@gmail.com"]
|
11
|
+
s.homepage = "https://github.com/michalorman/enumerated"
|
12
|
+
s.summary = %q{Yet another enumeration gem for ActiveRecord}
|
13
|
+
s.description = %q{Goal of the Enumerated gem is to provide support to use enumerations on selection/drop down lists.}
|
14
|
+
|
15
|
+
s.rubyforge_project = "enumerated"
|
16
|
+
|
17
|
+
s.add_development_dependency "rspec"
|
18
|
+
s.add_development_dependency "rcov"
|
19
|
+
s.add_development_dependency "activesupport", ["~> 3.0.0"]
|
20
|
+
s.add_development_dependency "activerecord", ["~> 3.0.0"]
|
21
|
+
s.add_development_dependency "sqlite3-ruby"
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
|
+
s.require_paths = ["lib"]
|
27
|
+
end
|
data/lib/enumerated.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
require 'enumerated/definition'
|
5
|
+
|
6
|
+
module Enumerated
|
7
|
+
def self.included(base)
|
8
|
+
base.extend ClassMethods
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
# Declares that given attribute is enumerated.
|
13
|
+
def enumerated(attr, enums, opts = {})
|
14
|
+
def opts.disabled?(sym)
|
15
|
+
include?(sym) && !self[sym]
|
16
|
+
end
|
17
|
+
|
18
|
+
class_eval do
|
19
|
+
@definitions ||= {}
|
20
|
+
@definitions[attr.to_sym] = Definition.new(self.to_s, attr.to_s, enums)
|
21
|
+
end
|
22
|
+
|
23
|
+
define_helper_methods(attr, opts)
|
24
|
+
define_label_methods(attr)
|
25
|
+
define_bang_methods(attr, enums)
|
26
|
+
apply_validations(attr, enums, opts)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def define_helper_methods(attr, opts)
|
32
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
33
|
+
def self.#{attr.to_s.pluralize}(opts = {})
|
34
|
+
@definitions[:#{attr.to_s}].to_a(opts )
|
35
|
+
end
|
36
|
+
def self.definitions
|
37
|
+
@definitions
|
38
|
+
end
|
39
|
+
EOS
|
40
|
+
|
41
|
+
unless opts.include?(:helper) && !opts[:helper]
|
42
|
+
helper = opts[:helper] || "#{self.to_s.pluralize}Helper"
|
43
|
+
if helper.is_a?(Module) || Object.const_defined?(helper.to_sym, false)
|
44
|
+
helper = helper.constantize unless helper.is_a?(Module)
|
45
|
+
helper.class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
46
|
+
def #{self.to_s.underscore}_#{attr.to_s.pluralize}(opts = {})
|
47
|
+
#{self.to_s}.#{attr.to_s.pluralize}(opts)
|
48
|
+
end
|
49
|
+
EOS
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def define_label_methods(attr)
|
55
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
56
|
+
def #{attr.to_s}_label
|
57
|
+
return nil unless self.class.definitions.include?(:#{attr.to_s}) && !#{attr}.blank?
|
58
|
+
self.class.definitions[:#{attr.to_s}].label(#{attr})
|
59
|
+
end
|
60
|
+
EOS
|
61
|
+
end
|
62
|
+
|
63
|
+
def define_bang_methods(attr, enums)
|
64
|
+
keys(enums).map(&:to_sym).each do |e|
|
65
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
66
|
+
def #{e}?
|
67
|
+
#{attr}.to_sym == :#{e}
|
68
|
+
end
|
69
|
+
def #{e}!
|
70
|
+
self.#{attr} = :#{e}
|
71
|
+
end
|
72
|
+
EOS
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def keys(collection)
|
77
|
+
collection.is_a?(Array) ? collection : collection.keys
|
78
|
+
end
|
79
|
+
|
80
|
+
def apply_validations(attr, enums, opts)
|
81
|
+
unless opts.disabled?(:validate)
|
82
|
+
inclusion = opts.disabled?(:nillable) ?
|
83
|
+
"#{keys(enums).map(&:to_sym).to_s} + #{keys(enums).map(&:to_s).to_s}" :
|
84
|
+
"[nil, ''] + #{keys(enums).map(&:to_sym).to_s} + #{keys(enums).map(&:to_s).to_s}"
|
85
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
86
|
+
validates :#{attr.to_s}, :inclusion => #{inclusion}
|
87
|
+
EOS
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
ActiveRecord::Base.send(:include, Enumerated)
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Enumerated
|
2
|
+
|
3
|
+
# Wraps single enumerated definition declared in model.
|
4
|
+
class Definition
|
5
|
+
|
6
|
+
def initialize(model, attribute, declaration)
|
7
|
+
@model, @attribute, @declaration = model, attribute, declaration
|
8
|
+
raise ArgumentError, "Declared enumeration must be either Array or Hash." unless declaration.is_a?(Array) || declaration.is_a?(Hash)
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_a(opts = {})
|
12
|
+
result = filtered for_select, opts
|
13
|
+
result = overridden result, opts
|
14
|
+
ordered result, opts
|
15
|
+
end
|
16
|
+
|
17
|
+
def label(key)
|
18
|
+
@declaration.is_a?(Hash) ? @declaration[key.to_sym] : resolve_label(key)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def resolve_label(key)
|
24
|
+
I18n.t key.to_s, :default => key.to_s.humanize, :scope => %w(activerecord enumerations) + [@model.downcase, @attribute]
|
25
|
+
end
|
26
|
+
|
27
|
+
def for_select
|
28
|
+
return @declaration.invert.to_a if @declaration.is_a?(Hash)
|
29
|
+
result = []
|
30
|
+
@declaration.each do |d|
|
31
|
+
result << [resolve_label(d), d]
|
32
|
+
end
|
33
|
+
result
|
34
|
+
end
|
35
|
+
|
36
|
+
def ordered(arr, opts)
|
37
|
+
return arr if opts.empty? || !opts.include?(:order)
|
38
|
+
ordered = []
|
39
|
+
opts[:order].each do |o|
|
40
|
+
ordered << arr.select { |a| a[1].to_sym == o.to_sym }[0]
|
41
|
+
end
|
42
|
+
ordered
|
43
|
+
end
|
44
|
+
|
45
|
+
def filtered(arr, opts)
|
46
|
+
return arr if opts.empty? || !(opts.include?(:except) || opts.include?(:only))
|
47
|
+
raise ArgumentError, "Cannot pass both :except and :only parameters!" if opts.include?(:except) && opts.include?(:only)
|
48
|
+
opts.include?(:except) ? except(arr, opts[:except]) : only(arr, opts[:only])
|
49
|
+
end
|
50
|
+
|
51
|
+
def except(arr, keys)
|
52
|
+
arr.reject { |a| keys.map(&:to_sym).include?(a[1].to_sym) }
|
53
|
+
end
|
54
|
+
|
55
|
+
def only(arr, keys)
|
56
|
+
arr.select { |a| keys.map(&:to_sym).include?(a[1].to_sym) }
|
57
|
+
end
|
58
|
+
|
59
|
+
def overridden(arr, opts)
|
60
|
+
return arr if opts.empty? || !opts.include?(:override)
|
61
|
+
opts[:override].each do |key, value|
|
62
|
+
arr.select { |a| a[1].to_sym == key.to_sym }[0][0] = value
|
63
|
+
end
|
64
|
+
arr
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
data/spec/dog_spec.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Dog do
|
4
|
+
|
5
|
+
context "when not assigned a name" do
|
6
|
+
before(:each) { subject.valid? }
|
7
|
+
|
8
|
+
it { should_not be_valid }
|
9
|
+
its(:errors) { should_not be_empty }
|
10
|
+
its(:errors) { should have(1).error_on(:name)}
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when assigned a name" do
|
14
|
+
before(:each) { subject.max!; subject.valid? }
|
15
|
+
|
16
|
+
it { should be_valid }
|
17
|
+
its(:name) { should == :max }
|
18
|
+
its(:errors) { should be_empty }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when assigned an invalid name" do
|
22
|
+
before(:each) { subject.name = :woof; subject.valid? }
|
23
|
+
|
24
|
+
it { should_not be_valid }
|
25
|
+
its(:errors) { should_not be_empty }
|
26
|
+
its(:errors) { should have(1).error_on(:name)}
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when assigned a blank name" do
|
30
|
+
before(:each) { subject.name = ""; subject.valid? }
|
31
|
+
|
32
|
+
its(:name) { should == "" }
|
33
|
+
it { should_not be_valid }
|
34
|
+
its(:errors) { should_not be_empty }
|
35
|
+
its(:errors) { should have(1).error_on(:name)}
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'fixtures/helpers'
|
2
|
+
|
3
|
+
I18n.load_path << File.join(File.dirname(__FILE__), '..', 'locales', 'en.yml')
|
4
|
+
|
5
|
+
class User < ActiveRecord::Base
|
6
|
+
enumerated :gender, [:male, :female]
|
7
|
+
enumerated :hair, {black: "Black hair", brown: "Brown hair", red: "Red hair", blond: "Blond hair"}, :helper => HairsHelper, :validate => false
|
8
|
+
enumerated :nationality, %w(gbr esp pol), :helper => false
|
9
|
+
end
|
10
|
+
|
11
|
+
class Dog < ActiveRecord::Base
|
12
|
+
enumerated :name, %w(max sam), :nillable => false
|
13
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe HairsHelper do
|
4
|
+
it { should have_defined_method :user_hairs }
|
5
|
+
it { should_not have_defined_method :user_genders }
|
6
|
+
it { should_not have_defined_method :user_nationalities }
|
7
|
+
|
8
|
+
context "should include method" do
|
9
|
+
subject { Class.new { include HairsHelper }.new }
|
10
|
+
|
11
|
+
its(:user_hairs) { should == [["Black hair", :black], ["Brown hair", :brown], ["Red hair", :red], ["Blond hair", :blond]] }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "parametrized" do
|
15
|
+
subject { Class.new { include HairsHelper }.new }
|
16
|
+
|
17
|
+
it "should return user hairs in brown, black, blond, red order" do
|
18
|
+
subject.user_hairs(:order => %w(brown black blond red)).should == [["Brown hair", :brown], ["Black hair", :black], ["Blond hair", :blond], ["Red hair", :red]]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return user hairs except brown, black and blond" do
|
22
|
+
subject.user_hairs(:except => %w(brown black blond)).should == [["Red hair", :red]]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return only blond, red user hairs" do
|
26
|
+
subject.user_hairs(:only => %w(blond red), :order => %w(blond red)).should == [["Blond hair", :blond], ["Red hair", :red]]
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should override the labels for red and black" do
|
30
|
+
subject.user_hairs(:order => [:red, :blond, :brown, :black], :override => {:red => "Shiny Red Hair", :black => "Hell Black Hair"}).should == [["Shiny Red Hair", :red], ["Blond hair", :blond], ["Brown hair", :brown], ["Hell Black Hair", :black]]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/spec/locales/en.yml
ADDED
data/spec/matchers.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'enumerated'
|
3
|
+
require 'fixtures/models'
|
4
|
+
require 'matchers'
|
5
|
+
|
6
|
+
ActiveRecord::Base.establish_connection({'adapter' => 'sqlite3', 'database' => ':memory:'})
|
7
|
+
|
8
|
+
connection = ActiveRecord::Base.connection
|
9
|
+
|
10
|
+
connection.create_table(:users, :force => true) do |t|
|
11
|
+
t.string :gender
|
12
|
+
t.string :hair
|
13
|
+
t.string :nationality
|
14
|
+
end
|
15
|
+
|
16
|
+
connection.create_table(:dogs, :force => true) do |t|
|
17
|
+
t.string :name
|
18
|
+
end
|
data/spec/user_spec.rb
ADDED
@@ -0,0 +1,245 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe User do
|
4
|
+
|
5
|
+
it { should include_module Enumerated }
|
6
|
+
it { should respond_to :gender }
|
7
|
+
it { should respond_to :gender= }
|
8
|
+
it { should respond_to :hair }
|
9
|
+
it { should respond_to :hair= }
|
10
|
+
it { should respond_to :nationality }
|
11
|
+
it { should respond_to :nationality= }
|
12
|
+
it { should be_valid }
|
13
|
+
|
14
|
+
its(:gender) { should == nil }
|
15
|
+
its(:gender_label) { should == nil }
|
16
|
+
its(:hair) { should == nil }
|
17
|
+
its(:hair_label) { should == nil }
|
18
|
+
|
19
|
+
context "class" do
|
20
|
+
subject { User.new.class }
|
21
|
+
|
22
|
+
it { should respond_to :genders }
|
23
|
+
it { should respond_to :hairs }
|
24
|
+
it { should respond_to :nationalities }
|
25
|
+
|
26
|
+
its(:genders) { should == [["Male", :male], ["Female", :female]] }
|
27
|
+
its(:hairs) { should == [["Black hair", :black], ["Brown hair", :brown], ["Red hair", :red], ["Blond hair", :blond]] }
|
28
|
+
its(:nationalities) { should == [["English", "gbr"], ["Spanish", "esp"], ["Polish", "pol"]] }
|
29
|
+
|
30
|
+
context "ordered" do
|
31
|
+
it "should return genders in female, male order" do
|
32
|
+
subject.genders(:order => [:female, :male]).should == [["Female", :female], ["Male", :male]]
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return hairs in red, blond, brown, black order" do
|
36
|
+
subject.hairs(:order => [:red, :blond, :brown, :black]).should == [["Red hair", :red], ["Blond hair", :blond], ["Brown hair", :brown], ["Black hair", :black]]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should return nationalities in pol, esp, gbr order" do
|
40
|
+
subject.nationalities(:order => [:pol, :esp, :gbr]).should == [["Polish", "pol"], ["Spanish", "esp"], ["English", "gbr"]]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "except" do
|
45
|
+
it "should return genders except male" do
|
46
|
+
subject.genders(:except => [:male]).should == [["Female", :female]]
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should return hairs except brown and black" do
|
50
|
+
subject.hairs(:order => [:red, :blond], :except => [:brown, :black]).should == [["Red hair", :red], ["Blond hair", :blond]]
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should return nationalities except pol" do
|
54
|
+
subject.nationalities(:order => [:esp, :gbr], :except => [:pol]).should == [["Spanish", "esp"], ["English", "gbr"]]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "only" do
|
59
|
+
it "should return only male gender" do
|
60
|
+
subject.genders(:only => [:male]).should == [["Male", :male]]
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should return only brown and black hair" do
|
64
|
+
subject.hairs(:order => [:brown, :black], :only => [:brown, :black]).should == [["Brown hair", :brown], ["Black hair", :black]]
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should return only pol nationality" do
|
68
|
+
subject.nationalities(:only => [:pol]).should == [["Polish", "pol"]]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "override" do
|
73
|
+
it "should override the label for female" do
|
74
|
+
subject.genders(:override => {:female => "Madam"}).should == [["Male", :male], ["Madam", :female]]
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should override the labels for red and black" do
|
78
|
+
subject.hairs(:order => [:red, :blond, :brown, :black], :override => { :red => "Shiny Red Hair", :black => "Hell Black Hair" }).should == [["Shiny Red Hair", :red], ["Blond hair", :blond], ["Brown hair", :brown], ["Hell Black Hair", :black]]
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should override the label for pol" do
|
82
|
+
subject.nationalities(:except => [:gbr], :order => [:esp, :pol], :override => { :pol => "Polak" }).should == [["Spanish", "esp"], ["Polak", "pol"]]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "when assigned a gender" do
|
88
|
+
before(:each) { subject.gender = :female }
|
89
|
+
|
90
|
+
it { should be_valid }
|
91
|
+
its(:gender) { should == :female }
|
92
|
+
its(:gender_label) { should == "Female" }
|
93
|
+
its(:female?) { should == true }
|
94
|
+
its(:male?) { should == false }
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when assigned a gender using bang method" do
|
98
|
+
before(:each) { subject.male! }
|
99
|
+
|
100
|
+
it { should be_valid }
|
101
|
+
its(:gender) { should == :male }
|
102
|
+
its(:gender_label) { should == "Male" }
|
103
|
+
its(:female?) { should == false }
|
104
|
+
its(:male?) { should == true }
|
105
|
+
end
|
106
|
+
|
107
|
+
context "when assigned a gender as string" do
|
108
|
+
before(:each) { subject.gender = "female" }
|
109
|
+
|
110
|
+
it { should be_valid }
|
111
|
+
its(:gender) { should == "female" }
|
112
|
+
its(:gender_label) { should == "Female" }
|
113
|
+
its(:female?) { should == true }
|
114
|
+
its(:male?) { should == false }
|
115
|
+
end
|
116
|
+
|
117
|
+
context "when assigned an invalid gender" do
|
118
|
+
before(:each) { subject.gender = :unknown; subject.valid? }
|
119
|
+
|
120
|
+
it { should_not be_valid }
|
121
|
+
|
122
|
+
its(:errors) { should_not be_empty }
|
123
|
+
its(:errors) { should have(1).error_on(:gender) }
|
124
|
+
end
|
125
|
+
|
126
|
+
context "when assigned a blank gender" do
|
127
|
+
before(:each) { subject.gender = "" }
|
128
|
+
|
129
|
+
it { should be_valid }
|
130
|
+
its(:gender) { should == "" }
|
131
|
+
its(:gender_label) { should == nil }
|
132
|
+
its(:female?) { should == false }
|
133
|
+
its(:male?) { should == false }
|
134
|
+
end
|
135
|
+
|
136
|
+
context "when assigned a hair" do
|
137
|
+
before(:each) { subject.hair = :blond }
|
138
|
+
|
139
|
+
it { should be_valid }
|
140
|
+
its(:hair) { should == :blond }
|
141
|
+
its(:hair_label) { should == "Blond hair" }
|
142
|
+
its(:black?) { should == false }
|
143
|
+
its(:brown?) { should == false }
|
144
|
+
its(:red?) { should == false }
|
145
|
+
its(:blond?) { should == true }
|
146
|
+
end
|
147
|
+
|
148
|
+
context "when assigned a hair using bang method" do
|
149
|
+
before(:each) { subject.red! }
|
150
|
+
|
151
|
+
it { should be_valid }
|
152
|
+
its(:hair) { should == :red }
|
153
|
+
its(:hair_label) { should == "Red hair" }
|
154
|
+
its(:black?) { should == false }
|
155
|
+
its(:brown?) { should == false }
|
156
|
+
its(:red?) { should == true }
|
157
|
+
its(:blond?) { should == false }
|
158
|
+
end
|
159
|
+
|
160
|
+
context "when assigned a hair as string" do
|
161
|
+
before(:each) { subject.hair = "brown" }
|
162
|
+
|
163
|
+
it { should be_valid }
|
164
|
+
its(:hair) { should == "brown" }
|
165
|
+
its(:hair_label) { should == "Brown hair" }
|
166
|
+
its(:black?) { should == false }
|
167
|
+
its(:brown?) { should == true }
|
168
|
+
its(:red?) { should == false }
|
169
|
+
its(:blond?) { should == false }
|
170
|
+
end
|
171
|
+
|
172
|
+
context "when assigned a blank hair" do
|
173
|
+
before(:each) { subject.hair = "" }
|
174
|
+
|
175
|
+
it { should be_valid }
|
176
|
+
its(:hair) { should == "" }
|
177
|
+
its(:hair_label) { should == nil }
|
178
|
+
its(:black?) { should == false }
|
179
|
+
its(:brown?) { should == false }
|
180
|
+
its(:red?) { should == false }
|
181
|
+
its(:blond?) { should == false }
|
182
|
+
end
|
183
|
+
|
184
|
+
context "when assigned an invalid hair" do
|
185
|
+
# Validation for :hair is turned off
|
186
|
+
before(:each) { subject.hair = :curly; subject.valid? }
|
187
|
+
|
188
|
+
it { should be_valid }
|
189
|
+
its(:errors) { should be_empty }
|
190
|
+
end
|
191
|
+
|
192
|
+
context "when assigned a nationality" do
|
193
|
+
before(:each) { subject.nationality = :esp }
|
194
|
+
|
195
|
+
it { should be_valid }
|
196
|
+
its(:nationality) { should == :esp }
|
197
|
+
its(:nationality_label) { should == "Spanish" }
|
198
|
+
its(:gbr?) { should == false }
|
199
|
+
its(:esp?) { should == true }
|
200
|
+
its(:pol?) { should == false }
|
201
|
+
end
|
202
|
+
|
203
|
+
context "when assigned a nationality using bang method" do
|
204
|
+
before(:each) { subject.pol! }
|
205
|
+
|
206
|
+
it { should be_valid }
|
207
|
+
its(:nationality) { should == :pol }
|
208
|
+
its(:nationality_label) { should == "Polish" }
|
209
|
+
its(:gbr?) { should == false }
|
210
|
+
its(:esp?) { should == false }
|
211
|
+
its(:pol?) { should == true }
|
212
|
+
end
|
213
|
+
|
214
|
+
context "when assigned a nationality as string" do
|
215
|
+
before(:each) { subject.nationality = "gbr" }
|
216
|
+
|
217
|
+
it { should be_valid }
|
218
|
+
its(:nationality) { should == "gbr" }
|
219
|
+
its(:nationality_label) { should == "English" }
|
220
|
+
its(:gbr?) { should == true }
|
221
|
+
its(:esp?) { should == false }
|
222
|
+
its(:pol?) { should == false }
|
223
|
+
end
|
224
|
+
|
225
|
+
context "when assigned a blank nationality" do
|
226
|
+
before(:each) { subject.nationality = "" }
|
227
|
+
|
228
|
+
it { should be_valid }
|
229
|
+
its(:nationality) { should == "" }
|
230
|
+
its(:nationality_label) { should == nil }
|
231
|
+
its(:gbr?) { should == false }
|
232
|
+
its(:esp?) { should == false }
|
233
|
+
its(:pol?) { should == false }
|
234
|
+
end
|
235
|
+
|
236
|
+
context "when assigned an invalid hair" do
|
237
|
+
before(:each) { subject.nationality = :rus; subject.valid? }
|
238
|
+
|
239
|
+
it { should_not be_valid }
|
240
|
+
|
241
|
+
its(:errors) { should_not be_empty }
|
242
|
+
its(:errors) { should have(1).error_on(:nationality) }
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe UsersHelper do
|
4
|
+
it { should have_defined_method :user_genders }
|
5
|
+
it { should_not have_defined_method :user_hairs }
|
6
|
+
it { should_not have_defined_method :user_nationalities }
|
7
|
+
|
8
|
+
context "should include method" do
|
9
|
+
subject { Class.new { include UsersHelper }.new }
|
10
|
+
|
11
|
+
its(:user_genders) { should == [["Male", :male], ["Female", :female]] }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "parametrized" do
|
15
|
+
subject { Class.new { include UsersHelper }.new }
|
16
|
+
|
17
|
+
it "should return user genders in female, male order" do
|
18
|
+
subject.user_genders(:order => [:female, :male]).should == [["Female", :female], ["Male", :male]]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return user genders except female" do
|
22
|
+
subject.user_genders(:except => [:female]).should == [["Male", :male]]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return only male as user genders" do
|
26
|
+
subject.user_genders(:only => [:male]).should == [["Male", :male]]
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should override the label for female" do
|
30
|
+
subject.user_genders(:override => {:female => "Madam"}).should == [["Male", :male], ["Madam", :female]]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: enumerated
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 1.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Michal Orman
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-01-28 00:00:00 +01:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :development
|
32
|
+
version_requirements: *id001
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rcov
|
35
|
+
prerelease: false
|
36
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
version: "0"
|
44
|
+
type: :development
|
45
|
+
version_requirements: *id002
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: activesupport
|
48
|
+
prerelease: false
|
49
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
segments:
|
55
|
+
- 3
|
56
|
+
- 0
|
57
|
+
- 0
|
58
|
+
version: 3.0.0
|
59
|
+
type: :development
|
60
|
+
version_requirements: *id003
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: activerecord
|
63
|
+
prerelease: false
|
64
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
segments:
|
70
|
+
- 3
|
71
|
+
- 0
|
72
|
+
- 0
|
73
|
+
version: 3.0.0
|
74
|
+
type: :development
|
75
|
+
version_requirements: *id004
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: sqlite3-ruby
|
78
|
+
prerelease: false
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
segments:
|
85
|
+
- 0
|
86
|
+
version: "0"
|
87
|
+
type: :development
|
88
|
+
version_requirements: *id005
|
89
|
+
description: Goal of the Enumerated gem is to provide support to use enumerations on selection/drop down lists.
|
90
|
+
email:
|
91
|
+
- michal.orman@gmail.com
|
92
|
+
executables: []
|
93
|
+
|
94
|
+
extensions: []
|
95
|
+
|
96
|
+
extra_rdoc_files: []
|
97
|
+
|
98
|
+
files:
|
99
|
+
- .gitignore
|
100
|
+
- .rspec
|
101
|
+
- .rvmrc
|
102
|
+
- Gemfile
|
103
|
+
- README.md
|
104
|
+
- Rakefile
|
105
|
+
- enumerator.gemspec
|
106
|
+
- lib/enumerated.rb
|
107
|
+
- lib/enumerated/definition.rb
|
108
|
+
- lib/enumerated/version.rb
|
109
|
+
- spec/dog_spec.rb
|
110
|
+
- spec/fixtures/helpers.rb
|
111
|
+
- spec/fixtures/models.rb
|
112
|
+
- spec/hairs_helper_spec.rb
|
113
|
+
- spec/locales/en.yml
|
114
|
+
- spec/matchers.rb
|
115
|
+
- spec/spec_helper.rb
|
116
|
+
- spec/user_spec.rb
|
117
|
+
- spec/users_helper_spec.rb
|
118
|
+
has_rdoc: true
|
119
|
+
homepage: https://github.com/michalorman/enumerated
|
120
|
+
licenses: []
|
121
|
+
|
122
|
+
post_install_message:
|
123
|
+
rdoc_options: []
|
124
|
+
|
125
|
+
require_paths:
|
126
|
+
- lib
|
127
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
128
|
+
none: false
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
segments:
|
133
|
+
- 0
|
134
|
+
version: "0"
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
segments:
|
141
|
+
- 0
|
142
|
+
version: "0"
|
143
|
+
requirements: []
|
144
|
+
|
145
|
+
rubyforge_project: enumerated
|
146
|
+
rubygems_version: 1.3.7
|
147
|
+
signing_key:
|
148
|
+
specification_version: 3
|
149
|
+
summary: Yet another enumeration gem for ActiveRecord
|
150
|
+
test_files: []
|
151
|
+
|