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 ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .idea/
6
+ *~
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/.rvmrc ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env bash
2
+
3
+ rvm --create 1.9.2@enumerated
4
+ rvm use 1.9.2@enumerated
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in enumerated.gemspec
4
+ gemspec
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
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -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
@@ -0,0 +1,3 @@
1
+ module Enumerated
2
+ VERSION = "1.0.1"
3
+ 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,3 @@
1
+ module UsersHelper; end
2
+
3
+ module HairsHelper; 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
@@ -0,0 +1,8 @@
1
+ en:
2
+ activerecord:
3
+ enumerations:
4
+ user:
5
+ nationality:
6
+ gbr: "English"
7
+ esp: "Spanish"
8
+ pol: "Polish"
data/spec/matchers.rb ADDED
@@ -0,0 +1,11 @@
1
+ RSpec::Matchers.define :include_module do |module_name|
2
+ match do |model|
3
+ model.class.include? module_name
4
+ end
5
+ end
6
+
7
+ RSpec::Matchers.define :have_defined_method do |method|
8
+ match do |mod|
9
+ mod.method_defined? method
10
+ end
11
+ end
@@ -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
+