enum_table 0.2.1 → 0.3.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.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