eav_hashes 1.0.1 → 1.0.2
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -20
- data/README.md +147 -147
- data/Rakefile +30 -30
- data/lib/eav_hashes/activerecord_extension.rb +37 -37
- data/lib/eav_hashes/eav_entry.rb +128 -128
- data/lib/eav_hashes/eav_hash.rb +167 -167
- data/lib/eav_hashes/util.rb +122 -122
- data/lib/eav_hashes/version.rb +5 -5
- data/lib/eav_hashes.rb +8 -8
- data/lib/generators/eav_migration/USAGE +26 -26
- data/lib/generators/eav_migration/eav_migration.rb +35 -35
- data/lib/generators/eav_migration/templates/eav_migration.erb +15 -15
- data/spec/dummy/README.rdoc +261 -261
- data/spec/dummy/Rakefile +7 -7
- data/spec/dummy/app/assets/javascripts/application.js +15 -15
- data/spec/dummy/app/assets/stylesheets/application.css +13 -13
- data/spec/dummy/app/controllers/application_controller.rb +3 -3
- data/spec/dummy/app/helpers/application_helper.rb +2 -2
- data/spec/dummy/app/models/custom_test_object.rb +6 -6
- data/spec/dummy/app/models/product.rb +3 -4
- data/spec/dummy/app/views/layouts/application.html.erb +14 -14
- data/spec/dummy/config/application.rb +62 -68
- data/spec/dummy/config/boot.rb +9 -9
- data/spec/dummy/config/database.yml +25 -25
- data/spec/dummy/config/environment.rb +5 -5
- data/spec/dummy/config/environments/development.rb +34 -37
- data/spec/dummy/config/environments/production.rb +70 -67
- data/spec/dummy/config/environments/test.rb +34 -37
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -7
- data/spec/dummy/config/initializers/inflections.rb +15 -15
- data/spec/dummy/config/initializers/mime_types.rb +5 -5
- data/spec/dummy/config/initializers/secret_token.rb +7 -7
- data/spec/dummy/config/initializers/session_store.rb +8 -8
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -14
- data/spec/dummy/config/locales/en.yml +5 -5
- data/spec/dummy/config/routes.rb +58 -58
- data/spec/dummy/config.ru +4 -4
- data/spec/dummy/db/migrate/20121206133059_create_products.rb +9 -9
- data/spec/dummy/db/migrate/20121210055854_create_product_tech_specs.rb +15 -15
- data/spec/dummy/db/seeds.rb +30 -30
- data/spec/dummy/public/404.html +26 -26
- data/spec/dummy/public/422.html +26 -26
- data/spec/dummy/public/500.html +25 -25
- data/spec/dummy/script/rails +6 -6
- data/spec/lib/eav_hashes/eav_hash_spec.rb +147 -137
- data/spec/lib/generators/eav_migration_spec.rb +60 -60
- data/spec/spec_helper.rb +24 -24
- metadata +25 -44
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/schema.rb +0 -35
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/ENV=test.log +0 -1
- data/spec/dummy/log/development.log +0 -46
- data/spec/dummy/log/test.log +0 -4623
data/lib/eav_hashes/util.rb
CHANGED
@@ -1,122 +1,122 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module EavHashes
|
3
|
-
module Util
|
4
|
-
# Sanity checks!
|
5
|
-
# @param [Hash] options the options hash to check for emptyness and Hashiness
|
6
|
-
def self.sanity_check(options)
|
7
|
-
raise "options cannot be empty (and you shouldn't be calling this since you left options blank)" if
|
8
|
-
(!options.is_a? Hash) or options.empty?
|
9
|
-
end
|
10
|
-
|
11
|
-
# Fills in any options not explicitly passed to eav_hash_for and creates an EavEntry type for the table
|
12
|
-
# @param [Hash] options the options hash to be filled with defaults on unset keys.
|
13
|
-
def self.fill_options_hash(options)
|
14
|
-
sanity_check options
|
15
|
-
|
16
|
-
# Generate a unique class name based on the eav_hash's name and owner
|
17
|
-
options[:entry_class_name] ||= "#{options[:parent_class_name]}_#{options[:hash_name]}_entry".camelize.to_sym
|
18
|
-
|
19
|
-
# Strip "_entries" from the table name
|
20
|
-
if /Entry$/.match options[:entry_class_name]
|
21
|
-
options[:table_name] ||= options[:entry_class_name].to_s.tableize.slice(0..-9).to_sym
|
22
|
-
else
|
23
|
-
options[:table_name] ||= options[:entry_class_name].to_s.tableize.to_sym
|
24
|
-
end
|
25
|
-
|
26
|
-
# Create the symbol name for the "belongs_to" association in the entry model
|
27
|
-
options[:parent_assoc_name] ||= "#{options[:parent_class_name].to_s.underscore}".to_sym
|
28
|
-
|
29
|
-
# Create the symbol name for the "has_many" association in the parent model
|
30
|
-
options[:entry_assoc_name] = options[:entry_class_name].to_s.tableize.to_sym
|
31
|
-
|
32
|
-
# Change slashes to underscores in options to match what's output by the generator
|
33
|
-
# TODO: Refactor table naming into one location
|
34
|
-
options[:table_name] = options[:table_name].to_s.gsub(/\//,'_').to_sym
|
35
|
-
options[:parent_assoc_name] = options[:parent_assoc_name].to_s.gsub(/\//,'_').to_sym
|
36
|
-
options[:entry_assoc_name] = options[:entry_assoc_name].to_s.gsub(/\//,'_').to_sym
|
37
|
-
|
38
|
-
# Create our custom type if it doesn't exist already
|
39
|
-
options[:entry_class] = create_eav_table_class options
|
40
|
-
|
41
|
-
return options
|
42
|
-
end
|
43
|
-
|
44
|
-
# Creates a new type subclassed from ActiveRecord::EavHashes::EavEntry which represents an eav_hash key-value pair
|
45
|
-
def self.create_eav_table_class (options)
|
46
|
-
sanity_check options
|
47
|
-
|
48
|
-
# Don't overwrite an existing type
|
49
|
-
return class_from_string(options[:entry_class_name].to_s) if class_from_string_exists?(options[:entry_class_name])
|
50
|
-
|
51
|
-
# Create our type
|
52
|
-
klass = set_constant_from_string options[:entry_class_name].to_s, Class.new(ActiveRecord::EavHashes::EavEntry)
|
53
|
-
|
54
|
-
# Fill in the associations and specify the table it belongs to
|
55
|
-
klass.class_eval <<-END_EVAL
|
56
|
-
self.table_name = "#{options[:table_name]}"
|
57
|
-
belongs_to :#{options[:parent_assoc_name]}
|
58
|
-
END_EVAL
|
59
|
-
|
60
|
-
return klass
|
61
|
-
end
|
62
|
-
|
63
|
-
# Searches an EavEntry's table for the specified key/value pair and returns an
|
64
|
-
# array containing the IDs of the models whose eav_hash key/value pair.
|
65
|
-
# You should not run this directly.
|
66
|
-
# @param [String, Symbol] key the key to search by
|
67
|
-
# @param [Object] value the value to search by. if this is nil, it will return all models which contain `key`
|
68
|
-
# @param [Hash] options the options hash which eav_hash_for hash generated.
|
69
|
-
def self.run_find_expression (key, value, options)
|
70
|
-
sanity_check options
|
71
|
-
raise "Can't search for a nil key!" if key.nil?
|
72
|
-
if value.nil?
|
73
|
-
options[:entry_class].where(
|
74
|
-
"entry_key = ? and symbol_key = ?",
|
75
|
-
key.to_s,
|
76
|
-
key.is_a?(Symbol)
|
77
|
-
).pluck("#{options[:parent_assoc_name]}_id".to_sym)
|
78
|
-
else
|
79
|
-
val_type = EavEntry.get_value_type value
|
80
|
-
if val_type == EavEntry::SUPPORTED_TYPES[:Object]
|
81
|
-
raise "Can't search by Objects/Hashes/Arrays!"
|
82
|
-
else
|
83
|
-
options[:entry_class].where(
|
84
|
-
"entry_key = ? and symbol_key = ? and value = ? and value_type = ?",
|
85
|
-
key.to_s,
|
86
|
-
key.is_a?(Symbol),
|
87
|
-
value.to_s,
|
88
|
-
val_type
|
89
|
-
).pluck("#{options[:parent_assoc_name]}_id".to_sym)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
# Find a class even if it's contained in one or more modules.
|
95
|
-
# See http://stackoverflow.com/questions/3163641/get-a-class-by-name-in-ruby
|
96
|
-
def self.class_from_string(str)
|
97
|
-
str.split('::').inject(Object) do |mod, class_name|
|
98
|
-
mod.const_get(class_name)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
# Check whether a class exists, even if it's contained in one or more modules.
|
103
|
-
def self.class_from_string_exists?(str)
|
104
|
-
begin
|
105
|
-
class_from_string(str)
|
106
|
-
rescue
|
107
|
-
return false
|
108
|
-
end
|
109
|
-
true
|
110
|
-
end
|
111
|
-
|
112
|
-
# Set a constant from a string, even if the string contains modules. Modules
|
113
|
-
# are created if necessary.
|
114
|
-
def self.set_constant_from_string(str, val)
|
115
|
-
parent = str.deconstantize.split('::').inject(Object) do |mod, class_name|
|
116
|
-
mod.const_defined?(class_name) ? mod.const_get(class_name) : mod.const_set(class_name, Module.new())
|
117
|
-
end
|
118
|
-
parent.const_set(str.demodulize.to_sym, val)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module EavHashes
|
3
|
+
module Util
|
4
|
+
# Sanity checks!
|
5
|
+
# @param [Hash] options the options hash to check for emptyness and Hashiness
|
6
|
+
def self.sanity_check(options)
|
7
|
+
raise "options cannot be empty (and you shouldn't be calling this since you left options blank)" if
|
8
|
+
(!options.is_a? Hash) or options.empty?
|
9
|
+
end
|
10
|
+
|
11
|
+
# Fills in any options not explicitly passed to eav_hash_for and creates an EavEntry type for the table
|
12
|
+
# @param [Hash] options the options hash to be filled with defaults on unset keys.
|
13
|
+
def self.fill_options_hash(options)
|
14
|
+
sanity_check options
|
15
|
+
|
16
|
+
# Generate a unique class name based on the eav_hash's name and owner
|
17
|
+
options[:entry_class_name] ||= "#{options[:parent_class_name]}_#{options[:hash_name]}_entry".camelize.to_sym
|
18
|
+
|
19
|
+
# Strip "_entries" from the table name
|
20
|
+
if /Entry$/.match options[:entry_class_name]
|
21
|
+
options[:table_name] ||= options[:entry_class_name].to_s.tableize.slice(0..-9).to_sym
|
22
|
+
else
|
23
|
+
options[:table_name] ||= options[:entry_class_name].to_s.tableize.to_sym
|
24
|
+
end
|
25
|
+
|
26
|
+
# Create the symbol name for the "belongs_to" association in the entry model
|
27
|
+
options[:parent_assoc_name] ||= "#{options[:parent_class_name].to_s.underscore}".to_sym
|
28
|
+
|
29
|
+
# Create the symbol name for the "has_many" association in the parent model
|
30
|
+
options[:entry_assoc_name] = options[:entry_class_name].to_s.tableize.to_sym
|
31
|
+
|
32
|
+
# Change slashes to underscores in options to match what's output by the generator
|
33
|
+
# TODO: Refactor table naming into one location
|
34
|
+
options[:table_name] = options[:table_name].to_s.gsub(/\//,'_').to_sym
|
35
|
+
options[:parent_assoc_name] = options[:parent_assoc_name].to_s.gsub(/\//,'_').to_sym
|
36
|
+
options[:entry_assoc_name] = options[:entry_assoc_name].to_s.gsub(/\//,'_').to_sym
|
37
|
+
|
38
|
+
# Create our custom type if it doesn't exist already
|
39
|
+
options[:entry_class] = create_eav_table_class options
|
40
|
+
|
41
|
+
return options
|
42
|
+
end
|
43
|
+
|
44
|
+
# Creates a new type subclassed from ActiveRecord::EavHashes::EavEntry which represents an eav_hash key-value pair
|
45
|
+
def self.create_eav_table_class (options)
|
46
|
+
sanity_check options
|
47
|
+
|
48
|
+
# Don't overwrite an existing type
|
49
|
+
return class_from_string(options[:entry_class_name].to_s) if class_from_string_exists?(options[:entry_class_name])
|
50
|
+
|
51
|
+
# Create our type
|
52
|
+
klass = set_constant_from_string options[:entry_class_name].to_s, Class.new(ActiveRecord::EavHashes::EavEntry)
|
53
|
+
|
54
|
+
# Fill in the associations and specify the table it belongs to
|
55
|
+
klass.class_eval <<-END_EVAL
|
56
|
+
self.table_name = "#{options[:table_name]}"
|
57
|
+
belongs_to :#{options[:parent_assoc_name]}
|
58
|
+
END_EVAL
|
59
|
+
|
60
|
+
return klass
|
61
|
+
end
|
62
|
+
|
63
|
+
# Searches an EavEntry's table for the specified key/value pair and returns an
|
64
|
+
# array containing the IDs of the models whose eav_hash key/value pair.
|
65
|
+
# You should not run this directly.
|
66
|
+
# @param [String, Symbol] key the key to search by
|
67
|
+
# @param [Object] value the value to search by. if this is nil, it will return all models which contain `key`
|
68
|
+
# @param [Hash] options the options hash which eav_hash_for hash generated.
|
69
|
+
def self.run_find_expression (key, value, options)
|
70
|
+
sanity_check options
|
71
|
+
raise "Can't search for a nil key!" if key.nil?
|
72
|
+
if value.nil?
|
73
|
+
options[:entry_class].where(
|
74
|
+
"entry_key = ? and symbol_key = ?",
|
75
|
+
key.to_s,
|
76
|
+
key.is_a?(Symbol)
|
77
|
+
).pluck("#{options[:parent_assoc_name]}_id".to_sym)
|
78
|
+
else
|
79
|
+
val_type = EavEntry.get_value_type value
|
80
|
+
if val_type == EavEntry::SUPPORTED_TYPES[:Object]
|
81
|
+
raise "Can't search by Objects/Hashes/Arrays!"
|
82
|
+
else
|
83
|
+
options[:entry_class].where(
|
84
|
+
"entry_key = ? and symbol_key = ? and value = ? and value_type = ?",
|
85
|
+
key.to_s,
|
86
|
+
key.is_a?(Symbol),
|
87
|
+
value.to_s,
|
88
|
+
val_type
|
89
|
+
).pluck("#{options[:parent_assoc_name]}_id".to_sym)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Find a class even if it's contained in one or more modules.
|
95
|
+
# See http://stackoverflow.com/questions/3163641/get-a-class-by-name-in-ruby
|
96
|
+
def self.class_from_string(str)
|
97
|
+
str.split('::').inject(Object) do |mod, class_name|
|
98
|
+
mod.const_get(class_name)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Check whether a class exists, even if it's contained in one or more modules.
|
103
|
+
def self.class_from_string_exists?(str)
|
104
|
+
begin
|
105
|
+
class_from_string(str)
|
106
|
+
rescue
|
107
|
+
return false
|
108
|
+
end
|
109
|
+
true
|
110
|
+
end
|
111
|
+
|
112
|
+
# Set a constant from a string, even if the string contains modules. Modules
|
113
|
+
# are created if necessary.
|
114
|
+
def self.set_constant_from_string(str, val)
|
115
|
+
parent = str.deconstantize.split('::').inject(Object) do |mod, class_name|
|
116
|
+
mod.const_defined?(class_name) ? mod.const_get(class_name) : mod.const_set(class_name, Module.new())
|
117
|
+
end
|
118
|
+
parent.const_set(str.demodulize.to_sym, val)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
data/lib/eav_hashes/version.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
module ActiveRecord
|
2
|
-
module EavHashes
|
3
|
-
VERSION = "1.0.
|
4
|
-
end
|
5
|
-
end
|
1
|
+
module ActiveRecord
|
2
|
+
module EavHashes
|
3
|
+
VERSION = "1.0.2"
|
4
|
+
end
|
5
|
+
end
|
data/lib/eav_hashes.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require "eav_hashes/util"
|
2
|
-
require "eav_hashes/eav_entry"
|
3
|
-
require "eav_hashes/eav_hash"
|
4
|
-
require "eav_hashes/activerecord_extension"
|
5
|
-
require "generators/eav_migration/eav_migration"
|
6
|
-
|
7
|
-
# tally-ho!
|
8
|
-
ActiveRecord::Base.send :include, ActiveRecord::EavHashes
|
1
|
+
require "eav_hashes/util"
|
2
|
+
require "eav_hashes/eav_entry"
|
3
|
+
require "eav_hashes/eav_hash"
|
4
|
+
require "eav_hashes/activerecord_extension"
|
5
|
+
require "generators/eav_migration/eav_migration"
|
6
|
+
|
7
|
+
# tally-ho!
|
8
|
+
ActiveRecord::Base.send :include, ActiveRecord::EavHashes
|
@@ -1,26 +1,26 @@
|
|
1
|
-
Description:
|
2
|
-
Creates a DB migration to generate the schema for a table which is used to
|
3
|
-
store the entries of an eav_hash.
|
4
|
-
|
5
|
-
Example:
|
6
|
-
If you're not setting a custom table name, i.e., your model looks like this:
|
7
|
-
|
8
|
-
class ModelName < ActiveRecord::Base
|
9
|
-
eav_hash_for :hash_name
|
10
|
-
end
|
11
|
-
|
12
|
-
Then simply run this migration like so:
|
13
|
-
|
14
|
-
rails generate eav_migration ModelName hash_name
|
15
|
-
|
16
|
-
However, if you're a wizard and have specified a custom table name like this:
|
17
|
-
|
18
|
-
class ModelName < ActiveRecord::Base
|
19
|
-
eav_hash_for :hash_name, :table_name => :custom_table
|
20
|
-
end
|
21
|
-
|
22
|
-
Then run this generator like this:
|
23
|
-
|
24
|
-
rails generate eav_migration ModelName hash_name custom_table
|
25
|
-
|
26
|
-
Easy as pie!
|
1
|
+
Description:
|
2
|
+
Creates a DB migration to generate the schema for a table which is used to
|
3
|
+
store the entries of an eav_hash.
|
4
|
+
|
5
|
+
Example:
|
6
|
+
If you're not setting a custom table name, i.e., your model looks like this:
|
7
|
+
|
8
|
+
class ModelName < ActiveRecord::Base
|
9
|
+
eav_hash_for :hash_name
|
10
|
+
end
|
11
|
+
|
12
|
+
Then simply run this migration like so:
|
13
|
+
|
14
|
+
rails generate eav_migration ModelName hash_name
|
15
|
+
|
16
|
+
However, if you're a wizard and have specified a custom table name like this:
|
17
|
+
|
18
|
+
class ModelName < ActiveRecord::Base
|
19
|
+
eav_hash_for :hash_name, :table_name => :custom_table
|
20
|
+
end
|
21
|
+
|
22
|
+
Then run this generator like this:
|
23
|
+
|
24
|
+
rails generate eav_migration ModelName hash_name custom_table
|
25
|
+
|
26
|
+
Easy as pie!
|
@@ -1,36 +1,36 @@
|
|
1
|
-
require 'rails/generators'
|
2
|
-
require 'rails/generators/active_record'
|
3
|
-
|
4
|
-
class EavMigrationGenerator < ActiveRecord::Generators::Base
|
5
|
-
|
6
|
-
source_root File.expand_path "../templates", __FILE__
|
7
|
-
# small hack to override NamedBase displaying NAME
|
8
|
-
argument :name, :required => true, :type => :string, :banner => "<ModelName>"
|
9
|
-
argument :hash_name, :required => true, :type => :string, :banner => "<hash_name>"
|
10
|
-
argument :custom_table_name, :required => false, :type => :string, :banner => "table_name"
|
11
|
-
|
12
|
-
def create_eav_migration
|
13
|
-
p name
|
14
|
-
migration_template "eav_migration.erb", "db/migrate/#{migration_file_name}.rb"
|
15
|
-
end
|
16
|
-
|
17
|
-
def migration_file_name
|
18
|
-
"create_" + table_name
|
19
|
-
end
|
20
|
-
|
21
|
-
def migration_name
|
22
|
-
migration_file_name.camelize
|
23
|
-
end
|
24
|
-
|
25
|
-
def table_name
|
26
|
-
custom_table_name || "#{name}_#{hash_name}".underscore.gsub(/\//, '_')
|
27
|
-
end
|
28
|
-
|
29
|
-
def model_name
|
30
|
-
name
|
31
|
-
end
|
32
|
-
|
33
|
-
def model_association_name
|
34
|
-
model_name.underscore.gsub(/\//,'_')
|
35
|
-
end
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
|
4
|
+
class EavMigrationGenerator < ActiveRecord::Generators::Base
|
5
|
+
|
6
|
+
source_root File.expand_path "../templates", __FILE__
|
7
|
+
# small hack to override NamedBase displaying NAME
|
8
|
+
argument :name, :required => true, :type => :string, :banner => "<ModelName>"
|
9
|
+
argument :hash_name, :required => true, :type => :string, :banner => "<hash_name>"
|
10
|
+
argument :custom_table_name, :required => false, :type => :string, :banner => "table_name"
|
11
|
+
|
12
|
+
def create_eav_migration
|
13
|
+
p name
|
14
|
+
migration_template "eav_migration.erb", "db/migrate/#{migration_file_name}.rb"
|
15
|
+
end
|
16
|
+
|
17
|
+
def migration_file_name
|
18
|
+
"create_" + table_name
|
19
|
+
end
|
20
|
+
|
21
|
+
def migration_name
|
22
|
+
migration_file_name.camelize
|
23
|
+
end
|
24
|
+
|
25
|
+
def table_name
|
26
|
+
custom_table_name || "#{name}_#{hash_name}".underscore.gsub(/\//, '_')
|
27
|
+
end
|
28
|
+
|
29
|
+
def model_name
|
30
|
+
name
|
31
|
+
end
|
32
|
+
|
33
|
+
def model_association_name
|
34
|
+
model_name.underscore.gsub(/\//,'_')
|
35
|
+
end
|
36
36
|
end
|
@@ -1,16 +1,16 @@
|
|
1
|
-
class <%= migration_name %> < ActiveRecord::Migration
|
2
|
-
def change
|
3
|
-
create_table :<%= table_name %> do |t|
|
4
|
-
t.references :<%= model_association_name %>, :null => false
|
5
|
-
t.string :entry_key, :null => false
|
6
|
-
t.text :value, :null => false
|
7
|
-
t.integer :value_type, :null => false
|
8
|
-
t.boolean :symbol_key, :null => false, :default => true
|
9
|
-
|
10
|
-
t.timestamps
|
11
|
-
end
|
12
|
-
|
13
|
-
add_index :<%= table_name %>, :<%= model_association_name %>_id
|
14
|
-
add_index :<%= table_name %>, :entry_key
|
15
|
-
end
|
1
|
+
class <%= migration_name %> < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :<%= table_name %> do |t|
|
4
|
+
t.references :<%= model_association_name %>, :null => false
|
5
|
+
t.string :entry_key, :null => false
|
6
|
+
t.text :value, :null => false
|
7
|
+
t.integer :value_type, :null => false
|
8
|
+
t.boolean :symbol_key, :null => false, :default => true
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
|
13
|
+
add_index :<%= table_name %>, :<%= model_association_name %>_id
|
14
|
+
add_index :<%= table_name %>, :entry_key
|
15
|
+
end
|
16
16
|
end
|