enumerate 0.0.4

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0db9d3a63909d2f1e942fc7c9d72ee6df9129de4
4
+ data.tar.gz: bac591dc7038aa835d7244bde5573f1e328fdcbd
5
+ SHA512:
6
+ metadata.gz: 781cedc5ede92afbdb33ba49cc4b659f7d61d0627c15ac76bf46e8c3bb2f0d26b27b3b955506b1ce540fca604d1d191c0f2d2abc4fd94fd85ef8857918b308ff
7
+ data.tar.gz: cdb2002e9c61cc372c8093e7c00b9de5fdc2f77787c8bb150218232404c5aa99399631213e190de45bd089036fca5a31da80cd667bb6c06fb17f7eb97acb3ff9
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ gemfile:
6
+ - gemfiles/rails31.gemfile
7
+ - gemfiles/rails32.gemfile
8
+ - gemfiles/rails40.gemfile
9
+ matrix:
10
+ exclude:
11
+ - rvm: 1.9.3
12
+ gemfile: gemfiles/rails40.gemfile
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in enumerate.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Dale Stevens
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,80 @@
1
+ # Enumerate [![Build Status](https://secure.travis-ci.org/TwilightCoders/enumerate.png)](http://travis-ci.org/TwilightCoders/enumerate)
2
+ # Enumerate [![Gem Version](https://badge.fury.io/rb/enumerate.png)](http://badge.fury.io/rb/enumerate)
3
+
4
+ Enumerate adds an enum command to all ActiveRecord models which enables you to work with integer and string attributes as if they were enums
5
+
6
+ ## Installing
7
+
8
+ Just add the enumerate gem to your GemFile
9
+
10
+ ```ruby
11
+ gem 'enumerate'
12
+ ```
13
+
14
+ ## How to use
15
+
16
+ Just call the enum function in any ActiveRecord object, the function accepts the field name as the first variable and the possible values as an array
17
+
18
+ ```ruby
19
+ class Event < ActiveRecord::Base
20
+ enum :status, [:available, :canceled, :completed]
21
+ end
22
+ ```
23
+
24
+ If your status column is of type integer, Enumerate will assign the indices of the array as the values stored in the database.
25
+
26
+ :available will be 0
27
+ :canceled will be 1
28
+ :completed will be 2
29
+
30
+ If you wish to specify yourself, simply use a hash
31
+
32
+ ```ruby
33
+ class Event < ActiveRecord::Base
34
+ enum :status, {:available => 0, :canceled => 2, :completed => 5}
35
+ end
36
+ ```
37
+
38
+ After that you get several autogenerated commands to use with the enum
39
+
40
+ ```ruby
41
+ # Access through field name
42
+
43
+ event.status # returns the enum's current value as a symbol
44
+ event.status = :canceled # sets the enum's value to canceled (can also get a string)
45
+
46
+
47
+ # Shorthand methods, access through the possible values
48
+
49
+ event.available? # returns true if enum's current status is available
50
+ event.canceled! # changes the enum's value to canceled
51
+
52
+ # Get all the possible values
53
+
54
+ Event::STATUSES # returns all available status of the enum
55
+ ```
56
+
57
+ ## Options
58
+ #### :allow_nil
59
+ By default the enum field does not support a nil value. In order to allow nil values add the `allow_nil` option (similar to the Rails validation option).
60
+
61
+ ```ruby
62
+ class Event < ActiveRecord::Base
63
+ enum :status, [:available, :canceled, :completed], :allow_nil => true
64
+ end
65
+
66
+ Event.create! # Is valid and does not throw an exception.
67
+ ```
68
+
69
+ ## Scopes
70
+ One last thing that the enumerate gem does is created scope (formerly nested_scopes) so you can easly query by the enum
71
+
72
+ For example if you want to count all the events that are canceled you can just run
73
+
74
+ ```ruby
75
+ Event.canceled.count
76
+ ```
77
+
78
+ ---
79
+
80
+ Copyright (c) 2013 Dale Stevens, released under the MIT license
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+ require 'appraisal'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ task :default => :spec
@@ -0,0 +1,11 @@
1
+ appraise "rails31" do
2
+ gem "activerecord", "~> 3.1.12"
3
+ end
4
+
5
+ appraise "rails32" do
6
+ gem "activerecord", "~> 3.2.14"
7
+ end
8
+
9
+ appraise "rails40" do
10
+ gem "activerecord", "~> 4.0.0"
11
+ end
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "enumerate/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "enumerate"
7
+ s.version = Enumerate::VERSION
8
+ s.authors = ["Dale"]
9
+ s.email = ["dale@twilightcoders.net"]
10
+ s.homepage = "http://github.com/twilightcoders/enumerate"
11
+ s.summary = %q{Enumerate adds an `enumerate` command to all ActiveRecord models, enabling you to work with string or integer columns as if they were enums.}
12
+ s.description = <<-END
13
+ Enumerate adds an `enumerate` command to all ActiveRecord models, enabling you to work with string or integer columns as if they were enums.
14
+
15
+ The following features are added to your model:
16
+ Validation - ensures that the field only receives accepted values
17
+ Predicate Methods - adds ? and ! functions for each enum value
18
+ Scopes - you can easily query for values of the enum
19
+ END
20
+ s.license = 'MIT'
21
+
22
+
23
+ # s.rubyforge_project = "enumerate"
24
+
25
+ s.files = `git ls-files`.split("\n") - ["Gemfile.lock"]
26
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
27
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
28
+ s.require_paths = ["lib"]
29
+
30
+ # specify any dependencies here; for example:
31
+ s.add_development_dependency "rake"
32
+ s.add_development_dependency "rspec"
33
+ s.add_development_dependency "activerecord", '>= 3.0'
34
+ s.add_development_dependency "sqlite3"
35
+ s.add_development_dependency 'appraisal', '>= 0.3.8'
36
+ end
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "activerecord", "~> 3.1.12"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "activerecord", "~> 3.2.14"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "activerecord", "~> 4.0.0"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,3 @@
1
+ require "enumerate/version"
2
+ require "enumerate/model"
3
+ require "enumerate/railtie" if defined? Rails
@@ -0,0 +1,74 @@
1
+ module Enumerate
2
+ module Model
3
+ def enumerate(attribute, vals={}, opts={})
4
+
5
+ validates_inclusion_of attribute, :in => vals, :allow_nil => !!opts[:allow_nil]
6
+
7
+ # Get the column type of the attribute. We support int and string
8
+ col_type = self.columns_hash[attribute.to_s].type
9
+
10
+ const_hash_name = attribute.to_s.pluralize.upcase
11
+
12
+ if col_type == :string
13
+ vals = Hash[vals.zip vals.map{ |s| s.to_s }] if vals.kind_of?(Array)
14
+ elsif col_type == :integer
15
+ # Converts an array into a hash of values with indicies as the "values"
16
+ vals = Hash[vals.zip (0...vals.size)] if vals.kind_of?(Array)
17
+ else
18
+ raise "Unsupported column type for enumeration :#{attribute} in #{self.class}!"
19
+ end
20
+
21
+ # Ensure that only arrays and hashes are appropriate datatypes.
22
+ raise "Unsupported values datatype for enumeration :#{attribute} in #{self.class}!" if !vals.kind_of?(Hash)
23
+
24
+ # Sets a class costant with the enumerated values
25
+ const_set(const_hash_name, vals)
26
+
27
+ setup_accessors(const_hash_name, attribute)
28
+
29
+ setup_predicates(vals, attribute)
30
+
31
+ end
32
+
33
+ private
34
+
35
+ def setup_accessors(const_hash_name, attribute)
36
+ unless methods.include?(attribute.to_s)
37
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
38
+ def #{attribute.to_s}
39
+ #{const_hash_name}.key(read_attribute(:#{attribute}))
40
+ end
41
+ RUBY
42
+ end
43
+
44
+ unless methods.include?("#{attribute.to_s}=")
45
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
46
+ def #{attribute.to_s}=(s)
47
+ write_attribute(:#{attribute}, #{const_hash_name}[s.to_sym])
48
+ end
49
+ RUBY
50
+ end
51
+ end
52
+
53
+ def setup_predicates(vals, attribute)
54
+ vals.each do |key, val|
55
+ raise "Collision in enumeration predicate method(s) #{key}" if respond_to?("#{key.to_s}?") or respond_to?("#{key.to_s}!") or respond_to?("#{key.to_s}")
56
+
57
+ define_method "#{key.to_s}?" do
58
+ send("#{attribute.to_s}") == key
59
+ end
60
+
61
+ define_method "#{key.to_s}!" do
62
+ send("#{attribute.to_s}=", key)
63
+ end
64
+
65
+ # Define helper scopes
66
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
67
+ scope :#{key}, lambda { where(:#{attribute} => #{val}) }
68
+ RUBY
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ end
@@ -0,0 +1,9 @@
1
+ module UrlFormatter
2
+ class Railtie < Rails::Railtie
3
+ initializer 'enumerate.model' do
4
+ ActiveSupport.on_load :active_record do
5
+ extend Enumerate::Model
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module Enumerate
2
+ VERSION = '0.0.4'
3
+ end
@@ -0,0 +1,144 @@
1
+ require 'spec_helper'
2
+
3
+ class Model < ActiveRecord::Base
4
+ extend Enumerate::Model
5
+
6
+ enumerate :status, [:available, :canceled, :completed]
7
+ end
8
+
9
+ class OtherModel < ActiveRecord::Base
10
+ extend Enumerate::Model
11
+
12
+ belongs_to :model
13
+
14
+ enumerate :status, [:active, :expired, :not_expired]
15
+ end
16
+
17
+ class ModelAllowingNil < ActiveRecord::Base
18
+ self.table_name = 'models'
19
+
20
+ extend Enumerate::Model
21
+
22
+ belongs_to :model
23
+
24
+ enumerate :status, [:active, :expired, :not_expired], :allow_nil => true
25
+ end
26
+
27
+
28
+ describe :Enumerate do
29
+
30
+ before(:each) do
31
+ Model.delete_all
32
+ OtherModel.delete_all
33
+
34
+ @obj = Model.create!(:status => :available)
35
+ @canceled_obj = Model.create!(:status => :canceled)
36
+ @completed_obj = Model.create!(:status => :completed)
37
+
38
+ @active_obj = OtherModel.create!(:status => :active, :model => @obj)
39
+ @expired_obj = OtherModel.create!(:status => :expired, :model => @canceled_obj)
40
+ @not_expired_obj = OtherModel.create!(:status => :not_expired, :model => @canceled_obj)
41
+ end
42
+
43
+ describe "allow nil" do
44
+
45
+ before(:each) do
46
+ @obj_not_allowing_nil = Model.create
47
+ @obj_allowing_nil = ModelAllowingNil.create
48
+ end
49
+
50
+ describe "model allowing enum value to be nil" do
51
+ it "should be valid" do
52
+ @obj_allowing_nil.should be_valid
53
+ end
54
+
55
+ end
56
+
57
+ describe "model not allowing enum value to be nil" do
58
+ it "should be invalid" do
59
+ @obj_not_allowing_nil.should be_invalid
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+ describe "short hand methods" do
66
+ describe "question mark (?)" do
67
+ it "should return true if value of enum equals a value" do
68
+ @obj.available?.should be_true
69
+ end
70
+
71
+ it "should return false if value of enum is different " do
72
+ @obj.canceled?.should be_false
73
+ end
74
+
75
+ end
76
+
77
+ describe "exclemation mark (!)" do
78
+ it "should change the value of the enum to the methods value" do
79
+ @obj.canceled!
80
+ @obj.status.should == :canceled
81
+ end
82
+ end
83
+
84
+ it "should have two shorthand methods for each possible value" do
85
+ Model::STATUSES.each do |key, val|
86
+ @obj.respond_to?("#{key}?").should be_true
87
+ @obj.respond_to?("#{key}!").should be_true
88
+ end
89
+ end
90
+ end
91
+
92
+ describe "getting value" do
93
+ it "should always return the enums value as a symbol" do
94
+ @obj.status.should == :available
95
+ @obj.status = "canceled"
96
+ @obj.status.should == :canceled
97
+ end
98
+
99
+ end
100
+
101
+ describe "setting value" do
102
+ it "should except values as symbol" do
103
+ @obj.status = :canceled
104
+ @obj.canceled?.should be_true
105
+ end
106
+
107
+ it "should except values as string" do
108
+ @obj.status = "canceled"
109
+ @obj.canceled?.should be_true
110
+ end
111
+ end
112
+
113
+ describe "validations" do
114
+ it "should not except a value outside the given list" do
115
+ @obj = Model.new(:status => :available)
116
+ @obj.status = :foobar
117
+ @obj.should_not be_valid
118
+ end
119
+
120
+ it "should except value in the list" do
121
+ @obj = Model.new(:status => :available)
122
+ @obj.status = :canceled
123
+ @obj.should be_valid
124
+ end
125
+ end
126
+
127
+ describe "scopes" do
128
+ it "should return objects with given value" do
129
+ Model.available.should == [@obj]
130
+ Model.canceled.should == [@canceled_obj]
131
+ end
132
+
133
+ it "should return objects with given value when joined with models who have the same enum field" do
134
+ OtherModel.joins(:model).active.should == [@active_obj]
135
+ end
136
+
137
+ end
138
+
139
+
140
+ it "class should have a CONST that holds all the available options of the enum" do
141
+ Model::STATUSES.should include(:available, :canceled, :completed)
142
+ end
143
+
144
+ end
@@ -0,0 +1,19 @@
1
+ require 'enumerate'
2
+ require 'active_record'
3
+
4
+ def set_database
5
+ db_config = {:adapter => "sqlite3", :database => ":memory:"}
6
+ ActiveRecord::Base.establish_connection(db_config)
7
+ connection = ActiveRecord::Base.connection
8
+
9
+ connection.create_table :models do |t|
10
+ t.integer :status
11
+ end
12
+
13
+ connection.create_table :other_models do |t|
14
+ t.integer :status
15
+ t.references :model
16
+ end
17
+ end
18
+
19
+ set_database
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: enumerate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Dale
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activerecord
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: appraisal
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: 0.3.8
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: 0.3.8
83
+ description: |2
84
+ Enumerate adds an `enumerate` command to all ActiveRecord models, enabling you to work with string or integer columns as if they were enums.
85
+
86
+ The following features are added to your model:
87
+ Validation - ensures that the field only receives accepted values
88
+ Predicate Methods - adds ? and ! functions for each enum value
89
+ Scopes - you can easily query for values of the enum
90
+ email:
91
+ - dale@twilightcoders.net
92
+ executables: []
93
+ extensions: []
94
+ extra_rdoc_files: []
95
+ files:
96
+ - .gitignore
97
+ - .travis.yml
98
+ - Gemfile
99
+ - LICENSE
100
+ - README.md
101
+ - Rakefile
102
+ - appraisal
103
+ - enumerate.gemspec
104
+ - gemfiles/rails31.gemfile
105
+ - gemfiles/rails32.gemfile
106
+ - gemfiles/rails40.gemfile
107
+ - lib/enumerate.rb
108
+ - lib/enumerate/model.rb
109
+ - lib/enumerate/railtie.rb
110
+ - lib/enumerate/version.rb
111
+ - spec/enumerate/enum_spec.rb
112
+ - spec/spec_helper.rb
113
+ homepage: http://github.com/twilightcoders/enumerate
114
+ licenses:
115
+ - MIT
116
+ metadata: {}
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubyforge_project:
133
+ rubygems_version: 2.0.3
134
+ signing_key:
135
+ specification_version: 4
136
+ summary: Enumerate adds an `enumerate` command to all ActiveRecord models, enabling
137
+ you to work with string or integer columns as if they were enums.
138
+ test_files:
139
+ - spec/enumerate/enum_spec.rb
140
+ - spec/spec_helper.rb