active_enum 0.8.2 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ [0.9.0] : 2010-08-11
2
+ - Full ActiveModel support for enumerate extension. Use ActiveEnum.extend_classes array to indicate classes to extend.
3
+ - Added generator for initializer config file with all settings.
4
+ - Added setup block for config
5
+
1
6
  [0.8.2] : 2010-08-01
2
7
  - Fix method name clash of enum_for which is defined on Object
3
8
  - Refactor extension method definitions
@@ -15,6 +15,10 @@ Put this in your Gemfile
15
15
 
16
16
  gem 'active_enum'
17
17
 
18
+ Then generate the config initializer file
19
+
20
+ rails generate active_enum:install
21
+
18
22
 
19
23
  == Example
20
24
 
@@ -192,10 +196,7 @@ The input type will be automatically detected for enumerated attributes. You can
192
196
 
193
197
 
194
198
  == TODO
195
- * more docs
196
199
  * storage options of memory, database or yaml
197
200
  * use custom method name for the enumerated attribute
198
- * named_scopes
199
- * question methods for enum names e.g. user.male?
200
201
 
201
202
  Copyright (c) 2009 Adam Meehan, released under the MIT license
@@ -2,16 +2,16 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{active_enum}
5
- s.version = "0.8.2"
5
+ s.version = "0.9.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Adam Meehan"]
9
9
  s.autorequire = %q{active_enum}
10
- s.date = %q{2010-08-01}
10
+ s.date = %q{2010-08-11}
11
11
  s.description = %q{Define enum classes in Rails and use them to enumerate ActiveRecord attributes}
12
12
  s.email = %q{adam.meehan@gmail.com}
13
13
  s.extra_rdoc_files = ["README.rdoc"]
14
- s.files = ["active_enum.gemspec", "MIT-LICENSE", "CHANGELOG", "README.rdoc", "Rakefile", "lib/active_enum", "lib/active_enum/acts_as_enum.rb", "lib/active_enum/base.rb", "lib/active_enum/extensions.rb", "lib/active_enum/form_helpers", "lib/active_enum/form_helpers/formtastic.rb", "lib/active_enum/form_helpers/simple_form.rb", "lib/active_enum/storage", "lib/active_enum/storage/abstract_store.rb", "lib/active_enum/storage/memory_store.rb", "lib/active_enum/version.rb", "lib/active_enum.rb", "lib/generators", "spec/active_enum", "spec/active_enum/acts_as_enum_spec.rb", "spec/active_enum/base_spec.rb", "spec/active_enum/extensions_spec.rb", "spec/active_enum/form_helpers", "spec/active_enum/form_helpers/formtastic_spec.rb", "spec/active_enum/form_helpers/simple_form_spec.rb", "spec/active_enum/storage", "spec/active_enum/storage/memory_store_spec.rb", "spec/active_enum_spec.rb", "spec/schema.rb", "spec/spec_helper.rb"]
14
+ s.files = ["active_enum.gemspec", "MIT-LICENSE", "CHANGELOG", "README.rdoc", "Rakefile", "lib/active_enum", "lib/active_enum/acts_as_enum.rb", "lib/active_enum/base.rb", "lib/active_enum/extensions.rb", "lib/active_enum/form_helpers", "lib/active_enum/form_helpers/formtastic.rb", "lib/active_enum/form_helpers/simple_form.rb", "lib/active_enum/storage", "lib/active_enum/storage/abstract_store.rb", "lib/active_enum/storage/active_record_store.rb", "lib/active_enum/storage/memory_store.rb", "lib/active_enum/version.rb", "lib/active_enum.rb", "lib/generators", "lib/generators/active_enum", "lib/generators/active_enum/install_generator.rb", "lib/generators/active_enum/templates", "lib/generators/active_enum/templates/active_enum.rb", "spec/active_enum", "spec/active_enum/acts_as_enum_spec.rb", "spec/active_enum/base_spec.rb", "spec/active_enum/extensions_spec.rb", "spec/active_enum/form_helpers", "spec/active_enum/form_helpers/formtastic_spec.rb", "spec/active_enum/form_helpers/simple_form_spec.rb", "spec/active_enum/storage", "spec/active_enum/storage/active_record_store_spec.rb", "spec/active_enum/storage/memory_store_spec.rb", "spec/active_enum_spec.rb", "spec/schema.rb", "spec/spec_helper.rb"]
15
15
  s.homepage = %q{http://github.com/adzap/active_enum}
16
16
  s.require_paths = ["lib"]
17
17
  s.rubyforge_project = %q{active_enum}
@@ -6,15 +6,28 @@ require 'active_enum/version'
6
6
 
7
7
  module ActiveEnum
8
8
  mattr_accessor :enum_classes
9
- self.enum_classes = []
9
+ @@enum_classes = []
10
10
 
11
11
  mattr_accessor :use_name_as_value
12
- self.use_name_as_value = false
12
+ @@use_name_as_value = false
13
13
 
14
14
  mattr_accessor :storage
15
- self.storage = :memory
15
+ @@storage = :memory
16
16
 
17
- class Configuration
17
+ mattr_accessor :extend_classes
18
+ @@extend_classes = []
19
+
20
+ def self.extend_classes=(klasses)
21
+ @@extend_classes = klasses
22
+ klasses.each {|klass| klass.send(:include, ActiveEnum::Extensions) }
23
+ end
24
+
25
+ # Setup method for plugin configuration
26
+ def self.setup
27
+ yield self
28
+ end
29
+
30
+ class EnumDefinitions
18
31
  def enum(name, &block)
19
32
  class_name = name.to_s.camelize
20
33
  eval("class #{class_name} < ActiveEnum::Base; end", TOPLEVEL_BINDING)
@@ -23,9 +36,10 @@ module ActiveEnum
23
36
  end
24
37
  end
25
38
 
39
+ # Define enums in bulk
26
40
  def self.define(&block)
27
41
  raise "Define requires block" unless block_given?
28
- Configuration.new.instance_eval(&block)
42
+ EnumDefinitions.new.instance_eval(&block)
29
43
  end
30
44
 
31
45
  end
@@ -2,11 +2,11 @@ module ActiveEnum
2
2
  class EnumNotFound < StandardError; end
3
3
 
4
4
  module Extensions
5
+ extend ActiveSupport::Concern
5
6
 
6
- def self.included(base)
7
- base.extend ClassMethods
8
- base.class_inheritable_accessor :enumerated_attributes
9
- base.enumerated_attributes = {}
7
+ included do
8
+ class_inheritable_accessor :enumerated_attributes
9
+ self.enumerated_attributes = {}
10
10
  end
11
11
 
12
12
  module ClassMethods
@@ -122,5 +122,3 @@ module ActiveEnum
122
122
 
123
123
  end
124
124
  end
125
-
126
- ActiveRecord::Base.send :include, ActiveEnum::Extensions
@@ -0,0 +1,64 @@
1
+ module ActiveEnum
2
+ class Model < ActiveRecord::Base
3
+ set_table_name 'enums'
4
+ serialize :meta, Hash
5
+ end
6
+
7
+ module Storage
8
+ class ActiveRecordStore < AbstractStore
9
+ def initialize(enum_class, order)
10
+ super
11
+ @values = values_from_db
12
+ end
13
+
14
+ def set(id, name)
15
+ check_duplicate id, name
16
+ values << [id, name]
17
+ sort!
18
+ end
19
+
20
+ def get_by_id(id)
21
+ values.assoc(id)
22
+ end
23
+
24
+ def get_by_name(name)
25
+ values.rassoc(name.to_s) || values.rassoc(name.to_s.titleize)
26
+ end
27
+
28
+ def values
29
+ @values
30
+ end
31
+
32
+ def check_duplicate(id, name)
33
+ if get_by_id(id) || get_by_name(name)
34
+ raise ActiveEnum::DuplicateValue
35
+ end
36
+ end
37
+
38
+ def sort!
39
+ return if @order == :as_defined
40
+ case @order
41
+ when :asc
42
+ values.sort! {|a,b| a[0] <=> b[0] }
43
+ when :desc
44
+ values.sort! {|a,b| b[0] <=> a[0] }
45
+ end
46
+ end
47
+
48
+ def order_clause
49
+ @order_clause ||= case @order
50
+ when :asc
51
+ 'enum_id ASC'
52
+ when :desc
53
+ 'enum_id DESC'
54
+ else
55
+ 'modified_at ASC'
56
+ end
57
+ end
58
+
59
+ def values_from_db
60
+ ActiveEnum::Model.all(:conditions => {:enum_type => @enum.to_s}, :order => order_clause).map {|r| [r.enum_id, r.name] }
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,3 +1,3 @@
1
1
  module ActiveEnum
2
- VERSION = '0.8.2'
2
+ VERSION = '0.9.0'
3
3
  end
@@ -0,0 +1,14 @@
1
+ module ActiveEnum
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ desc "Copy ActiveEnum default files"
5
+ source_root File.expand_path('../templates', __FILE__)
6
+ class_option :template_engine
7
+
8
+ def copy_initializers
9
+ copy_file 'active_enum.rb', 'config/initializers/active_enum.rb'
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ # Form helper integration
2
+ # require 'active_enum/form_helpers/simple_form'
3
+ # require 'active_enum/form_helpers/formtastic
4
+
5
+ ActiveEnum.setup do |config|
6
+
7
+ # Extend classes to add enumerate method
8
+ config.extend_classes = [ ActiveRecord::Base ]
9
+
10
+ # Return name string as value for attribute method
11
+ # config.use_name_as_value = false
12
+
13
+ # Storage of values
14
+ # config.storage = :memory
15
+
16
+ end
17
+
18
+ # ActiveEnum.define do
19
+ #
20
+ # enum(:enum_name) do
21
+ # value 1 => 'Name'
22
+ # end
23
+ #
24
+ # end
@@ -0,0 +1,133 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+ require 'active_enum/storage/active_record_store'
3
+
4
+ class TestARStoreEnum < ActiveEnum::Base; end
5
+ class TestOtherAREnum < ActiveEnum::Base; end
6
+
7
+ describe ActiveEnum::Storage::ActiveRecordStore do
8
+ attr_accessor :store
9
+
10
+ context '#set' do
11
+ it 'should store value of id and name' do
12
+ store.set 1, 'Name 1'
13
+ store.values.should == [[1, 'Name 1']]
14
+ end
15
+
16
+ it 'should raise error if duplicate id' do
17
+ lambda {
18
+ store.set 1, 'Name 1'
19
+ store.set 1, 'Other Name'
20
+ }.should raise_error(ActiveEnum::DuplicateValue)
21
+ end
22
+
23
+ it 'should raise error if duplicate name' do
24
+ lambda {
25
+ store.set 1, 'Name 1'
26
+ store.set 2, 'Name 1'
27
+ }.should raise_error(ActiveEnum::DuplicateValue)
28
+ end
29
+
30
+ it 'should raise error if duplicate name matches title-case name' do
31
+ lambda {
32
+ store.set 1, 'Name 1'
33
+ store.set 2, 'name 1'
34
+ }.should raise_error(ActiveEnum::DuplicateValue)
35
+ end
36
+
37
+ it 'should create a record for values' do
38
+ store.set 1, 'Name 1'
39
+ ActiveEnum::Model.count.should == 1
40
+ r = ActiveEnum::Model.first
41
+ r.enum_id.should == 1
42
+ r.name.should == 'Name 1'
43
+ end
44
+ end
45
+
46
+ context "#values" do
47
+ it 'should return array of stored values' do
48
+ store.set 1, 'Name 1'
49
+ store.values.should == [[1, 'Name 1']]
50
+ end
51
+
52
+ it 'should return values for set enum only' do
53
+ alt_store.set 1, 'Other Name 1'
54
+ store.set 1, 'Name 1'
55
+ store.values.should == [[1, 'Name 1']]
56
+ end
57
+ end
58
+
59
+ context "#get_by_id" do
60
+ it 'should return the value for a given id' do
61
+ store.set 1, 'Name 1'
62
+ store.get_by_id(1).should == [1, 'Name 1']
63
+ end
64
+
65
+ it 'should return nil when id not found' do
66
+ store.get_by_id(1).should be_nil
67
+ end
68
+
69
+ it 'should return value for correct enum' do
70
+ alt_store.set 1, 'Other Name 1'
71
+ store.set 1, 'Name 1'
72
+ store.get_by_id(1).should == [1, 'Name 1']
73
+ end
74
+ end
75
+
76
+ context "#get_by_name" do
77
+ it 'should return the value for a given name' do
78
+ store.set 1, 'Name 1'
79
+ store.get_by_name('Name 1').should == [1, 'Name 1']
80
+ end
81
+
82
+ it 'should return the value with title-cased name for a given lowercase name' do
83
+ store.set 1, 'Name 1'
84
+ store.get_by_name('name 1').should == [1, 'Name 1']
85
+ end
86
+
87
+ it 'should return nil when name not found' do
88
+ store.get_by_name('test name').should be_nil
89
+ end
90
+
91
+ it 'should return value for correct enum' do
92
+ alt_store.set 1, 'Other Name 1'
93
+ store.set 1, 'Name 1'
94
+ store.get_by_name('Name 1').should == [1, 'Name 1']
95
+ end
96
+ end
97
+
98
+ context "sort!" do
99
+ it 'should sort values ascending when passed :asc' do
100
+ @order = :asc
101
+ store.set 2, 'Name 2'
102
+ store.set 1, 'Name 1'
103
+ store.values.should == [[1,'Name 1'], [2, 'Name 2']]
104
+ end
105
+
106
+ it 'should sort values descending when passed :desc' do
107
+ @order = :desc
108
+ store.set 1, 'Name 1'
109
+ store.set 2, 'Name 2'
110
+ store.values.should == [[2, 'Name 2'], [1,'Name 1']]
111
+ end
112
+
113
+ it 'should not sort values when passed :as_defined' do
114
+ @order = :as_defined
115
+ store.set 1, 'Name 1'
116
+ store.set 3, 'Name 3'
117
+ store.set 2, 'Name 2'
118
+ store.values.should == [[1,'Name 1'], [3,'Name 3'], [2, 'Name 2']]
119
+ end
120
+ end
121
+
122
+ after do
123
+ ActiveEnum::Model.delete_all
124
+ end
125
+
126
+ def store
127
+ @store ||= ActiveEnum::Storage::ActiveRecordStore.new(TestARStoreEnum, @order)
128
+ end
129
+
130
+ def alt_store
131
+ @alt_store ||= ActiveEnum::Storage::ActiveRecordStore.new(TestOtherAREnum, :asc)
132
+ end
133
+ end
@@ -2,19 +2,44 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe "Bulk enum definitions" do
4
4
 
5
- it 'should define enum constants using block' do
6
- ActiveEnum.define do
7
- enum(:foo) do
8
- value :id => 1, :name => 'Foo 1'
9
- end
5
+ context ".define" do
6
+ it 'should define enum constants using block' do
7
+ ActiveEnum.define do
8
+ enum(:foo) do
9
+ value :id => 1, :name => 'Foo 1'
10
+ end
10
11
 
11
- enum(:bar) do
12
- value :id => 1, :name => 'Bar 1'
12
+ enum(:bar) do
13
+ value :id => 1, :name => 'Bar 1'
14
+ end
13
15
  end
16
+ Foo.all.should == [[1,'Foo 1']]
17
+ Bar.all.should == [[1,'Bar 1']]
14
18
  end
19
+ end
15
20
 
16
- Foo.all.should == [[1,'Foo 1']]
17
- Bar.all.should == [[1,'Bar 1']]
21
+ context ".setup" do
22
+ before :all do
23
+ @original = ActiveEnum.use_name_as_value
24
+ end
25
+
26
+ it 'should pass module into block as configuration object' do
27
+ ActiveEnum.use_name_as_value.should be_false
28
+ ActiveEnum.setup {|config| config.use_name_as_value = true }
29
+ ActiveEnum.use_name_as_value.should be_true
30
+ end
31
+
32
+ after :all do
33
+ ActiveEnum.use_name_as_value = @original
34
+ end
35
+ end
36
+
37
+ context ".extend_classes" do
38
+ it 'should add enumerate extensions to given classes' do
39
+ ActiveEnum.extend_classes = [ActiveRecord::Base, NotActiveRecord]
40
+ ActiveRecord::Base.should respond_to(:enumerate)
41
+ NotActiveRecord.should respond_to(:enumerate)
42
+ end
18
43
  end
19
44
 
20
45
  it 'should use the memory store by default' do
@@ -12,4 +12,15 @@ ActiveRecord::Schema.define(:version => 1) do
12
12
  t.string :name
13
13
  end
14
14
 
15
+ create_table :enums, :force => true do |t|
16
+ t.integer :enum_id
17
+ t.string :name
18
+ t.string :enum_type
19
+ t.string :meta
20
+ t.datetime :modified_at
21
+ end
22
+ add_index :enums, [:enum_id, :enum_type], :unique => true
23
+ add_index :enums, [:name, :enum_type]
24
+ add_index :enums, [:modified_at, :enum_type]
25
+
15
26
  end
@@ -19,6 +19,8 @@ ActiveRecord::Migration.verbose = false
19
19
  ActiveRecord::Base.establish_connection({:adapter => 'sqlite3', :database => ':memory:'})
20
20
  ActiveRecord::Base.logger = Logger.new('/dev/null')
21
21
 
22
+ ActiveEnum.extend_classes = [ActiveRecord::Base]
23
+
22
24
  require 'schema'
23
25
 
24
26
  class Person < ActiveRecord::Base; end
metadata CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 8
9
- - 2
10
- version: 0.8.2
8
+ - 9
9
+ - 0
10
+ version: 0.9.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Adam Meehan
@@ -15,7 +15,7 @@ autorequire: active_enum
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-01 00:00:00 +10:00
18
+ date: 2010-08-11 00:00:00 +10:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -39,14 +39,18 @@ files:
39
39
  - lib/active_enum/form_helpers/formtastic.rb
40
40
  - lib/active_enum/form_helpers/simple_form.rb
41
41
  - lib/active_enum/storage/abstract_store.rb
42
+ - lib/active_enum/storage/active_record_store.rb
42
43
  - lib/active_enum/storage/memory_store.rb
43
44
  - lib/active_enum/version.rb
44
45
  - lib/active_enum.rb
46
+ - lib/generators/active_enum/install_generator.rb
47
+ - lib/generators/active_enum/templates/active_enum.rb
45
48
  - spec/active_enum/acts_as_enum_spec.rb
46
49
  - spec/active_enum/base_spec.rb
47
50
  - spec/active_enum/extensions_spec.rb
48
51
  - spec/active_enum/form_helpers/formtastic_spec.rb
49
52
  - spec/active_enum/form_helpers/simple_form_spec.rb
53
+ - spec/active_enum/storage/active_record_store_spec.rb
50
54
  - spec/active_enum/storage/memory_store_spec.rb
51
55
  - spec/active_enum_spec.rb
52
56
  - spec/schema.rb