eav_hashes 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -20
  3. data/README.md +147 -147
  4. data/Rakefile +30 -30
  5. data/lib/eav_hashes/activerecord_extension.rb +37 -37
  6. data/lib/eav_hashes/eav_entry.rb +128 -128
  7. data/lib/eav_hashes/eav_hash.rb +167 -167
  8. data/lib/eav_hashes/util.rb +122 -122
  9. data/lib/eav_hashes/version.rb +5 -5
  10. data/lib/eav_hashes.rb +8 -8
  11. data/lib/generators/eav_migration/USAGE +26 -26
  12. data/lib/generators/eav_migration/eav_migration.rb +35 -35
  13. data/lib/generators/eav_migration/templates/eav_migration.erb +15 -15
  14. data/spec/dummy/README.rdoc +261 -261
  15. data/spec/dummy/Rakefile +7 -7
  16. data/spec/dummy/app/assets/javascripts/application.js +15 -15
  17. data/spec/dummy/app/assets/stylesheets/application.css +13 -13
  18. data/spec/dummy/app/controllers/application_controller.rb +3 -3
  19. data/spec/dummy/app/helpers/application_helper.rb +2 -2
  20. data/spec/dummy/app/models/custom_test_object.rb +6 -6
  21. data/spec/dummy/app/models/product.rb +3 -4
  22. data/spec/dummy/app/views/layouts/application.html.erb +14 -14
  23. data/spec/dummy/config/application.rb +62 -68
  24. data/spec/dummy/config/boot.rb +9 -9
  25. data/spec/dummy/config/database.yml +25 -25
  26. data/spec/dummy/config/environment.rb +5 -5
  27. data/spec/dummy/config/environments/development.rb +34 -37
  28. data/spec/dummy/config/environments/production.rb +70 -67
  29. data/spec/dummy/config/environments/test.rb +34 -37
  30. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -7
  31. data/spec/dummy/config/initializers/inflections.rb +15 -15
  32. data/spec/dummy/config/initializers/mime_types.rb +5 -5
  33. data/spec/dummy/config/initializers/secret_token.rb +7 -7
  34. data/spec/dummy/config/initializers/session_store.rb +8 -8
  35. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -14
  36. data/spec/dummy/config/locales/en.yml +5 -5
  37. data/spec/dummy/config/routes.rb +58 -58
  38. data/spec/dummy/config.ru +4 -4
  39. data/spec/dummy/db/migrate/20121206133059_create_products.rb +9 -9
  40. data/spec/dummy/db/migrate/20121210055854_create_product_tech_specs.rb +15 -15
  41. data/spec/dummy/db/seeds.rb +30 -30
  42. data/spec/dummy/public/404.html +26 -26
  43. data/spec/dummy/public/422.html +26 -26
  44. data/spec/dummy/public/500.html +25 -25
  45. data/spec/dummy/script/rails +6 -6
  46. data/spec/lib/eav_hashes/eav_hash_spec.rb +147 -137
  47. data/spec/lib/generators/eav_migration_spec.rb +60 -60
  48. data/spec/spec_helper.rb +24 -24
  49. metadata +25 -44
  50. data/spec/dummy/db/development.sqlite3 +0 -0
  51. data/spec/dummy/db/schema.rb +0 -35
  52. data/spec/dummy/db/test.sqlite3 +0 -0
  53. data/spec/dummy/log/ENV=test.log +0 -1
  54. data/spec/dummy/log/development.log +0 -46
  55. data/spec/dummy/log/test.log +0 -4623
@@ -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
@@ -1,5 +1,5 @@
1
- module ActiveRecord
2
- module EavHashes
3
- VERSION = "1.0.1"
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