enum_table 0.2.1 → 0.3.0

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/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ == 0.3.0 2013-12-12
2
+
3
+ * Fix initialize_attributes when options are passed. [Rebecca Miller-Webster]
4
+ * Lazily load enum mappings to avoid bootstrapping errors (migrating, seeding, etc.).
5
+
1
6
  == 0.2.1 2013-07-16
2
7
 
3
8
  * Fix SQL escaping.
@@ -131,6 +131,11 @@ it less disruptive to use strings instead. Do that with the `:type` option:
131
131
  * Include tests where practical.
132
132
  * Leave the version alone, or bump it in a separate commit.
133
133
 
134
+ ### Running tests
135
+ ```
136
+ testrb test
137
+ ```
138
+
134
139
  ## Copyright
135
140
 
136
141
  Copyright (c) HowAboutWe. See LICENSE for details.
@@ -7,6 +7,8 @@ Gem::Specification.new do |gem|
7
7
  gem.version = EnumTable::VERSION
8
8
  gem.authors = ['George Ogata']
9
9
  gem.email = ['george.ogata@gmail.com']
10
+ gem.license = 'MIT'
11
+ gem.date = Time.now.strftime('%Y-%m-%d')
10
12
  gem.summary = "Enumeration tables for ActiveRecord"
11
13
  gem.homepage = 'http://github.com/howaboutwe/enum_table'
12
14
 
@@ -4,37 +4,6 @@ module EnumTable
4
4
  autoload :Reflection, 'enum_table/reflection'
5
5
  autoload :SchemaDumper, 'enum_table/schema_dumper'
6
6
  autoload :SchemaStatements, 'enum_table/schema_statements'
7
-
8
- # Allow enum tables to be missing until missing_tables_disallowed is
9
- # called. This is invoked from rake tasks that create the enum tables, such as
10
- # Rails migration tasks.
11
- #
12
- # Missing table allowance is implemented as a thread-local stack to handle
13
- # nested invocations in multi-threaded programs.
14
- class << self
15
- def missing_tables_allowed
16
- missing_tables_allowances.push true
17
- end
18
-
19
- def missing_tables_disallowed
20
- missing_tables_allowances.pop
21
- end
22
-
23
- def missing_tables_allowed?
24
- !missing_tables_allowances.empty?
25
- end
26
-
27
- # Reset our state. Intended for testing Enum Table.
28
- def reset
29
- Thread.current[:enum_table_missing_tables_allowed] = nil
30
- end
31
-
32
- private
33
-
34
- def missing_tables_allowances
35
- Thread.current[:enum_table_missing_tables_allowed] ||= []
36
- end
37
- end
38
7
  end
39
8
 
40
9
  require 'enum_table/railtie' if defined?(Rails)
@@ -5,19 +5,9 @@ module EnumTable
5
5
  task :load_schema_dumper do
6
6
  require 'enum_table/schema_dumper'
7
7
  end
8
-
9
- task :allow_missing_tables do
10
- EnumTable.missing_tables_allowed
11
- end
12
8
  end
13
9
 
14
10
  Rake::Task['db:schema:dump'].prerequisites << 'enum_table:load_schema_dumper'
15
-
16
- %w'db:schema:load db:migrate db:migrate:up'.each do |task|
17
- task = Rake::Task[task]
18
- task.prerequisites.insert 0, 'enum_table:allow_missing_tables'
19
- task.enhance { EnumTable.missing_tables_disallowed }
20
- end
21
11
  end
22
12
  end
23
13
  end
@@ -15,8 +15,10 @@ module EnumTable
15
15
  value = options[key] and
16
16
  reflection.send "#{key}=", value
17
17
  end
18
- enum_map(name, options).each do |value, id|
19
- reflection.add_value id, value
18
+ reflection.to_populate do |ref|
19
+ enum_map(name, options).each do |value, id|
20
+ ref.add_value id, value
21
+ end
20
22
  end
21
23
  self.enums = enums.merge(name => reflection, name.to_s => reflection)
22
24
 
@@ -57,16 +59,13 @@ module EnumTable
57
59
  map = {}
58
60
  table.each_with_index { |element, i| map[element] = i + 1 }
59
61
  map
60
- when String, Symbol, nil
62
+ else
61
63
  map = {}
62
64
  table_name = table || "#{self.table_name.singularize}_#{name.to_s.pluralize}"
63
- return {} if EnumTable.missing_tables_allowed? && !connection.tables.include?(table_name)
64
65
  connection.execute("SELECT id, value FROM #{connection.quote_table_name table_name}").each do |row|
65
66
  map[row[1]] = row[0]
66
67
  end
67
68
  map
68
- else
69
- raise ArgumentError, "invalid table specifier: #{table.inspect}"
70
69
  end
71
70
  end
72
71
 
@@ -138,7 +137,7 @@ module EnumTable
138
137
  end
139
138
 
140
139
  # Enables state_machine to set initial values for states. Ick.
141
- def initialize_attributes(attributes) # :nodoc:
140
+ def initialize_attributes(attributes, *) # :nodoc:
142
141
  attributes = super
143
142
  enums.each do |name, reflection|
144
143
  if (value = attributes.delete(reflection.name.to_s))
@@ -10,6 +10,8 @@ module EnumTable
10
10
  @strings_to_ids = {}
11
11
  @values_to_ids = {}
12
12
  @ids_to_values = {}
13
+ @populate_procs = []
14
+ @populated = false
13
15
  end
14
16
 
15
17
  def initialize_copy(other)
@@ -20,11 +22,17 @@ module EnumTable
20
22
  @strings_to_ids = other.instance_variable_get(:@strings_to_ids).dup
21
23
  @values_to_ids = other.instance_variable_get(:@values_to_ids).dup
22
24
  @ids_to_values = other.instance_variable_get(:@ids_to_values).dup
25
+ @populate_procs = other.instance_variable_get(:@populate_procs).dup
26
+ @populated = false
23
27
  end
24
28
 
25
29
  attr_reader :name
26
30
  attr_accessor :id_name, :type
27
31
 
32
+ def to_populate(&block)
33
+ @populate_procs << block
34
+ end
35
+
28
36
  def add_value(id, value)
29
37
  @strings_to_ids[value.to_s] = id
30
38
 
@@ -34,6 +42,7 @@ module EnumTable
34
42
  end
35
43
 
36
44
  def id(value)
45
+ ensure_populated
37
46
  if value.is_a?(String) || type == :string
38
47
  @strings_to_ids[value.to_s.strip]
39
48
  else
@@ -42,11 +51,22 @@ module EnumTable
42
51
  end
43
52
 
44
53
  def value(id)
54
+ ensure_populated
45
55
  @ids_to_values[id]
46
56
  end
47
57
 
48
58
  def values
59
+ ensure_populated
49
60
  @values_to_ids.keys
50
61
  end
62
+
63
+ private
64
+
65
+ def ensure_populated
66
+ return if @populated
67
+ @populate_procs.each { |p| p.call(self) }
68
+ @populate_procs.clear
69
+ @populated = true
70
+ end
51
71
  end
52
72
  end
@@ -1,5 +1,5 @@
1
1
  module EnumTable
2
- VERSION = [0, 2, 1]
2
+ VERSION = [0, 3, 0]
3
3
 
4
4
  class << VERSION
5
5
  include Comparable
@@ -9,7 +9,7 @@ mysql2:
9
9
  password:
10
10
  database: enum_table_test
11
11
  postgresql:
12
- username: g
12
+ username: postgres
13
13
  password:
14
14
  database: enum_table_test
15
15
  min_messages: warning
@@ -17,7 +17,8 @@ describe EnumTable do
17
17
  describe '.enum' do
18
18
  before do
19
19
  connection.create_table(:user_genders) { |t| t.string :value }
20
- connection.execute "INSERT INTO user_genders(id, value) VALUES (1, 'female'), (2, 'male')"
20
+ connection.execute "INSERT INTO user_genders(id, value) VALUES (1, 'female')"
21
+ connection.execute "INSERT INTO user_genders(id, value) VALUES (2, 'male')"
21
22
  end
22
23
 
23
24
  it "defines an enum by a conventionally named table by default" do
@@ -45,14 +46,16 @@ describe EnumTable do
45
46
 
46
47
  it "accepts the :table name as a string" do
47
48
  connection.create_table(:custom_table) { |t| t.string :value }
48
- connection.execute "INSERT INTO custom_table(id, value) VALUES (1, 'male'), (2, 'female')"
49
+ connection.execute "INSERT INTO custom_table(id, value) VALUES (1, 'male')"
50
+ connection.execute "INSERT INTO custom_table(id, value) VALUES (2, 'female')"
49
51
  User.enum :gender, table: 'custom_table'
50
52
  User.enums[:gender].value(1).must_equal(:male)
51
53
  end
52
54
 
53
55
  it "accepts the :table name as a symbol" do
54
56
  connection.create_table(:custom_table) { |t| t.string :value }
55
- connection.execute "INSERT INTO custom_table(id, value) VALUES (1, 'male'), (2, 'female')"
57
+ connection.execute "INSERT INTO custom_table(id, value) VALUES (1, 'male')"
58
+ connection.execute "INSERT INTO custom_table(id, value) VALUES (2, 'female')"
56
59
  User.enum :gender, table: :custom_table
57
60
  User.enums[:gender].value(1).must_equal(:male)
58
61
  end
@@ -67,37 +70,24 @@ describe EnumTable do
67
70
  User.enums[:gender].value(1).must_equal :male
68
71
  end
69
72
 
70
- it "raises an ArgumentError if :table is something else" do
71
- ->{ User.enum :gender, table: Object.new }.must_raise ArgumentError, /invalid :table specifier/
72
- end
73
-
74
73
  it "passes other options to the Reflection" do
75
74
  User.enum :gender, id_name: :gender_number
76
75
  enum = User.enums[:gender]
77
76
  enum.id_name.must_equal :gender_number
78
77
  end
79
78
 
80
- describe "when missing tables are not allowed" do
81
- it "raises an error if the underlying table does not exist" do
82
- # must_raise does not do ancestor lookup in some versions of minitest
83
- # (notably the version that ships with Ruby 1.9.3). Avoid it until we
84
- # have a testrb that honors the Gemfile.
85
- exception = nil
86
- begin
87
- User.enum(:status)
88
- rescue => exception
89
- end
90
- exception.must_be_kind_of StandardError
91
- end
79
+ it "does not cry immediately if the enum table does not exist" do
80
+ User.enum(:status)
92
81
  end
93
82
 
94
- describe "when missing tables are allowed" do
95
- before { EnumTable.missing_tables_allowed }
96
- after { EnumTable.reset }
97
-
98
- it "does not raise an error if the underlying table does not exist" do
99
- User.enum :status
83
+ it "does cry when you first try to use the enum if the enum table does not exist" do
84
+ User.enum(:status)
85
+ exception = nil
86
+ begin
87
+ User.enum_id(:status, 'awesome')
88
+ rescue => exception
100
89
  end
90
+ exception.must_be_kind_of StandardError
101
91
  end
102
92
 
103
93
  describe "on a subclass" do
@@ -195,6 +185,10 @@ describe EnumTable do
195
185
  attributes['gender_id'].must_equal 1
196
186
  attributes.key?('gender').must_equal false
197
187
  end
188
+
189
+ it "should take an options hash in addition to the attributes hash and not raise an error" do
190
+ User.initialize_attributes({ 'gender' => 'female' }, { :some => :stuff }).wont_be_nil
191
+ end
198
192
  end
199
193
 
200
194
  describe "#enum_id" do
@@ -67,7 +67,8 @@ describe EnumTable::SchemaStatements do
67
67
  describe "#change_enum_table" do
68
68
  before do
69
69
  connection.execute "CREATE TABLE genders(id integer, value varchar(20))"
70
- connection.execute "INSERT INTO genders (id, value) VALUES (1, 'female'), (2, 'male')"
70
+ connection.execute "INSERT INTO genders (id, value) VALUES (1, 'female')"
71
+ connection.execute "INSERT INTO genders (id, value) VALUES (2, 'male')"
71
72
  end
72
73
 
73
74
  it "inserts values added in the block" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enum_table
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-16 00:00:00.000000000 Z
12
+ date: 2013-12-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -71,7 +71,8 @@ files:
71
71
  - test/enum_table/test_schema_statements.rb
72
72
  - test/test_helper.rb
73
73
  homepage: http://github.com/howaboutwe/enum_table
74
- licenses: []
74
+ licenses:
75
+ - MIT
75
76
  post_install_message:
76
77
  rdoc_options: []
77
78
  require_paths:
@@ -84,7 +85,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
84
85
  version: '0'
85
86
  segments:
86
87
  - 0
87
- hash: -950106288231480747
88
+ hash: 932469567180106626
88
89
  required_rubygems_version: !ruby/object:Gem::Requirement
89
90
  none: false
90
91
  requirements:
@@ -93,7 +94,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
94
  version: '0'
94
95
  segments:
95
96
  - 0
96
- hash: -950106288231480747
97
+ hash: 932469567180106626
97
98
  requirements: []
98
99
  rubyforge_project:
99
100
  rubygems_version: 1.8.25