eav_hashes 1.0.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.
Files changed (56) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +136 -0
  3. data/Rakefile +30 -0
  4. data/init.rb +1 -0
  5. data/lib/eav_hashes.rb +8 -0
  6. data/lib/eav_hashes/activerecord_extension.rb +37 -0
  7. data/lib/eav_hashes/eav_entry.rb +129 -0
  8. data/lib/eav_hashes/eav_hash.rb +168 -0
  9. data/lib/eav_hashes/util.rb +122 -0
  10. data/lib/eav_hashes/version.rb +5 -0
  11. data/lib/generators/eav_migration/USAGE +26 -0
  12. data/lib/generators/eav_migration/eav_migration.rb +36 -0
  13. data/lib/generators/eav_migration/templates/eav_migration.erb +16 -0
  14. data/lib/tasks/eav_hashes_tasks.rake +4 -0
  15. data/spec/dummy/README.rdoc +261 -0
  16. data/spec/dummy/Rakefile +7 -0
  17. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  18. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  19. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  20. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  21. data/spec/dummy/app/models/custom_test_object.rb +7 -0
  22. data/spec/dummy/app/models/product.rb +4 -0
  23. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  24. data/spec/dummy/config.ru +4 -0
  25. data/spec/dummy/config/application.rb +68 -0
  26. data/spec/dummy/config/boot.rb +10 -0
  27. data/spec/dummy/config/database.yml +25 -0
  28. data/spec/dummy/config/environment.rb +5 -0
  29. data/spec/dummy/config/environments/development.rb +37 -0
  30. data/spec/dummy/config/environments/production.rb +67 -0
  31. data/spec/dummy/config/environments/test.rb +37 -0
  32. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  33. data/spec/dummy/config/initializers/inflections.rb +15 -0
  34. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  35. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  36. data/spec/dummy/config/initializers/session_store.rb +8 -0
  37. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  38. data/spec/dummy/config/locales/en.yml +5 -0
  39. data/spec/dummy/config/routes.rb +58 -0
  40. data/spec/dummy/db/development.sqlite3 +0 -0
  41. data/spec/dummy/db/migrate/20121206133059_create_products.rb +9 -0
  42. data/spec/dummy/db/migrate/20121210055854_create_product_tech_specs.rb +16 -0
  43. data/spec/dummy/db/schema.rb +35 -0
  44. data/spec/dummy/db/seeds.rb +31 -0
  45. data/spec/dummy/db/test.sqlite3 +0 -0
  46. data/spec/dummy/log/development.log +46 -0
  47. data/spec/dummy/log/test.log +3878 -0
  48. data/spec/dummy/public/404.html +26 -0
  49. data/spec/dummy/public/422.html +26 -0
  50. data/spec/dummy/public/500.html +25 -0
  51. data/spec/dummy/public/favicon.ico +0 -0
  52. data/spec/dummy/script/rails +6 -0
  53. data/spec/lib/eav_hashes/eav_hash_spec.rb +138 -0
  54. data/spec/lib/generators/eav_migration_spec.rb +61 -0
  55. data/spec/spec_helper.rb +25 -0
  56. metadata +178 -0
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/404.html -->
21
+ <div class="dialog">
22
+ <h1>The page you were looking for doesn't exist.</h1>
23
+ <p>You may have mistyped the address or the page may have moved.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/422.html -->
21
+ <div class="dialog">
22
+ <h1>The change you wanted was rejected.</h1>
23
+ <p>Maybe you tried to change something you didn't have access to.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/500.html -->
21
+ <div class="dialog">
22
+ <h1>We're sorry, but something went wrong.</h1>
23
+ </div>
24
+ </body>
25
+ </html>
File without changes
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby.exe
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,138 @@
1
+ require 'spec_helper'
2
+
3
+ describe "EavHash/EavEntry" do
4
+ # p[1-3] are defined in spec/dummy/db/seeds.rb and are used as fixtures
5
+ let (:p1) { Product.find_by_name("Product 1") }
6
+ let (:p2) { Product.find_by_name("Product 2") }
7
+ let (:p3) { Product.find_by_name("Product 3") }
8
+
9
+ it "deletes an EAV row when its value is set to nil" do
10
+ p3_id = p3.id
11
+ p3.tech_specs[:delete_me] = nil
12
+ p3.save!
13
+
14
+ p3_pulled = Product.find_by_id(p3_id)
15
+ p3_pulled.tech_specs.keys.length.should == 0
16
+ end
17
+
18
+ it "is able to search for all models whose hashes contain a specified key" do
19
+ Product.find_by_tech_specs("A String").length.should be == 2
20
+ Product.find_by_tech_specs(:only_in_product_2).length.should be == 1
21
+ end
22
+
23
+ describe "distinguishes between string and symbol keys" do
24
+ it "finds a value for symbol key \":symbolic_key\" in Product 1" do
25
+ p1.tech_specs[:symbolic_key].should_not be_nil
26
+ end
27
+
28
+ it "does not find a value for non-symbol key \"symbolic_key\" in Product 1" do
29
+ p1.tech_specs["symbolic_key"].should be_nil
30
+ end
31
+ end
32
+
33
+ describe "preserves types between serialization and deserialization" do
34
+ it "preserves String value types" do
35
+ p1.tech_specs["A String"].should be_a_kind_of String
36
+ end
37
+
38
+ it "preserves Symbol value types" do
39
+ p1.tech_specs["A Symbol"].should be_a_kind_of Symbol
40
+ end
41
+
42
+ it "preserves Integer/Bignum/Fixnum value types" do
43
+ p1.tech_specs["A Number"].should be_a_kind_of Integer
44
+ end
45
+
46
+ it "preserves Symbol value types" do
47
+ p1.tech_specs["A Float"].should be_a_kind_of Float
48
+ end
49
+
50
+ it "preserves Complex value types" do
51
+ p1.tech_specs["A Complex"].should be_a_kind_of Complex
52
+ end
53
+
54
+ it "preserves Rational value types" do
55
+ p1.tech_specs["A Rational"].should be_a_kind_of Rational
56
+ end
57
+
58
+ it "preserves Boolean(true) value types" do
59
+ p1.tech_specs["True"].should be_a_kind_of TrueClass
60
+ end
61
+
62
+ it "preserves Boolean(false) value types" do
63
+ p1.tech_specs["False"].should be_a_kind_of FalseClass
64
+ end
65
+
66
+ it "preserves Array value types" do
67
+ p1.tech_specs["An Array"].should be_a_kind_of Array
68
+ end
69
+
70
+ it "preserves Hash value types" do
71
+ p1.tech_specs["A Hash"].should be_a_kind_of Hash
72
+ end
73
+
74
+ it "preserves user-defined value types" do
75
+ p1.tech_specs["An Object"].should be_a_kind_of CustomTestObject
76
+ end
77
+ end
78
+
79
+ describe "preserves values between serialization and deserialization" do
80
+ it "preserves String values" do
81
+ p1.tech_specs["A String"].should be == "Strings are for cats!"
82
+ end
83
+
84
+ it "preserves Symbols" do
85
+ p1.tech_specs["A Symbol"].should be == :symbol
86
+ end
87
+
88
+ it "preserves Integer/Bignum/Fixnum value types" do
89
+ p1.tech_specs["A Number"].should be == 42
90
+ end
91
+
92
+ it "preserves Symbol values" do
93
+ p1.tech_specs["A Float"].should be == 3.141592653589793
94
+ end
95
+
96
+ it "preserves Complex values" do
97
+ p1.tech_specs["A Complex"].should be == Complex("3.141592653589793+42i")
98
+ end
99
+
100
+ it "preserves Rational values" do
101
+ p1.tech_specs["A Rational"].should be == Rational(Math::PI)
102
+ end
103
+
104
+ it "preserves Boolean(true) values" do
105
+ p1.tech_specs["True"].should be == true
106
+ end
107
+
108
+ it "preserves Boolean(false) values" do
109
+ p1.tech_specs["False"].should be == false
110
+ end
111
+
112
+ it "preserves Array values" do
113
+ p1.tech_specs["An Array"].should be == ["blue", 42, :flux_capacitor]
114
+ end
115
+
116
+ it "preserves Hash values" do
117
+ p1.tech_specs["A Hash"].should be == {:foo => :bar}
118
+ end
119
+
120
+ it "preserves user-defined values" do
121
+ p1.tech_specs["An Object"].test_value.should be == 42
122
+ end
123
+ end
124
+
125
+ describe "cannot search by arrays, hashes, and objects" do
126
+ it "raises an error when searched by an object" do
127
+ lambda { Product.find_by_tech_specs("An Object", CustomTestObject.new(42)) }.should raise_error()
128
+ end
129
+
130
+ it "raises an error when searched by a hash" do
131
+ lambda { Product.find_by_tech_specs("A Hash", {:foo => :bar}) }.should raise_error()
132
+ end
133
+
134
+ it "raises an error when searched by an array" do
135
+ lambda { Product.find_by_tech_specs("An Array", ["blue", 42, :flux_capacitor]) }.should raise_error()
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe EavMigrationGenerator do
4
+ let(:top_level_model_generator) { EavMigrationGenerator.new(['TestModel', 'test_hash']) }
5
+ let(:one_module_generator) { EavMigrationGenerator.new(['Foo::TestModel', 'test_hash']) }
6
+ let(:multi_module_generator) { EavMigrationGenerator.new(['Foo::Bar::TestModel', 'test_hash']) }
7
+
8
+ describe "#model_association_name" do
9
+ context "when the model is at the top level" do
10
+ it "should underscore the model name" do
11
+ top_level_model_generator.model_association_name.should == "test_model"
12
+ end
13
+ end
14
+
15
+ context "when the model is namespaced by one module" do
16
+ it "should underscore the model name, replacing the slash with an underscore" do
17
+ one_module_generator.model_association_name.should == "foo_test_model"
18
+ end
19
+ end
20
+
21
+ context "when the model is namespaced by multiple modules" do
22
+ it "should underscore the model name, replacing the slashes with underscores" do
23
+ multi_module_generator.model_association_name.should == "foo_bar_test_model"
24
+ end
25
+ end
26
+ end
27
+
28
+ describe "#table_name" do
29
+ context "when the model is at the top level" do
30
+ it "should underscore the model name and append the hash name" do
31
+ top_level_model_generator.table_name.should == "test_model_test_hash"
32
+ end
33
+ end
34
+
35
+ context "when the model is namespaced by one module" do
36
+ it "should underscore the model name, replacing the slash with an underscore, and append the hash name" do
37
+ one_module_generator.table_name.should == "foo_test_model_test_hash"
38
+ end
39
+ end
40
+
41
+ context "when the model is namespaced by multiple modules" do
42
+ it "should underscore the model name, replacing the slashes with underscores, and append the hash name" do
43
+ multi_module_generator.table_name.should == "foo_bar_test_model_test_hash"
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "#migration_file_name" do
49
+ context "when the model is at the top level" do
50
+ it "should return create_ followed by the table name" do
51
+ top_level_model_generator.migration_file_name.should == "create_test_model_test_hash"
52
+ end
53
+ end
54
+
55
+ context "when the model is namespaced by one or more modules" do
56
+ it "should return create_ followed by the table name, with module names included" do
57
+ multi_module_generator.migration_file_name.should == "create_foo_bar_test_model_test_hash"
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,25 @@
1
+ # destroy our test DB before rails gets to open it
2
+ begin
3
+ File.delete File.expand_path("../dummy/db/test.sqlite3", __FILE__)
4
+ rescue
5
+ puts "Unable to delete test.sqlite3!\nDon't worry if this is the first time running specs."
6
+ end
7
+
8
+ ENV["RAILS_ENV"] = "test"
9
+ require File.expand_path("../dummy/config/environment.rb", __FILE__)
10
+
11
+ require 'rspec/rails'
12
+
13
+ Rails.backtrace_cleaner.remove_silencers!
14
+
15
+ # get some migrations up in here
16
+ ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__)
17
+ require File.expand_path("../dummy/db/seeds.rb", __FILE__)
18
+
19
+ RSpec.configure do |config|
20
+ require 'rspec/expectations'
21
+
22
+ #config.formatter = :documentation
23
+ config.use_transactional_fixtures = true
24
+ config.include RSpec::Matchers
25
+ end
metadata ADDED
@@ -0,0 +1,178 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: eav_hashes
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ilya Ostrovskiy
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.7
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 3.2.7
30
+ - !ruby/object:Gem::Dependency
31
+ name: sqlite3
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: ! " eav_hashes allows you to to leverage the power of the EAV database
47
+ model in the way you would expect to use it:\n a hash. Unlike other gems which
48
+ require you to create a special model and/or define which attributes you want to\n
49
+ \ have EAV behavior on (both of which defeat the purpose), all you need to do
50
+ with eav_hashes is add one line to your\n model and create a migration. All the
51
+ heavy lifting is done for you.\n"
52
+ email:
53
+ - ilya@200proof.cc
54
+ executables: []
55
+ extensions: []
56
+ extra_rdoc_files: []
57
+ files:
58
+ - lib/eav_hashes/activerecord_extension.rb
59
+ - lib/eav_hashes/eav_entry.rb
60
+ - lib/eav_hashes/eav_hash.rb
61
+ - lib/eav_hashes/util.rb
62
+ - lib/eav_hashes/version.rb
63
+ - lib/eav_hashes.rb
64
+ - lib/generators/eav_migration/eav_migration.rb
65
+ - lib/generators/eav_migration/templates/eav_migration.erb
66
+ - lib/generators/eav_migration/USAGE
67
+ - lib/tasks/eav_hashes_tasks.rake
68
+ - init.rb
69
+ - MIT-LICENSE
70
+ - Rakefile
71
+ - README.md
72
+ - spec/dummy/app/assets/javascripts/application.js
73
+ - spec/dummy/app/assets/stylesheets/application.css
74
+ - spec/dummy/app/controllers/application_controller.rb
75
+ - spec/dummy/app/helpers/application_helper.rb
76
+ - spec/dummy/app/models/custom_test_object.rb
77
+ - spec/dummy/app/models/product.rb
78
+ - spec/dummy/app/views/layouts/application.html.erb
79
+ - spec/dummy/config/application.rb
80
+ - spec/dummy/config/boot.rb
81
+ - spec/dummy/config/database.yml
82
+ - spec/dummy/config/environment.rb
83
+ - spec/dummy/config/environments/development.rb
84
+ - spec/dummy/config/environments/production.rb
85
+ - spec/dummy/config/environments/test.rb
86
+ - spec/dummy/config/initializers/backtrace_silencers.rb
87
+ - spec/dummy/config/initializers/inflections.rb
88
+ - spec/dummy/config/initializers/mime_types.rb
89
+ - spec/dummy/config/initializers/secret_token.rb
90
+ - spec/dummy/config/initializers/session_store.rb
91
+ - spec/dummy/config/initializers/wrap_parameters.rb
92
+ - spec/dummy/config/locales/en.yml
93
+ - spec/dummy/config/routes.rb
94
+ - spec/dummy/config.ru
95
+ - spec/dummy/db/development.sqlite3
96
+ - spec/dummy/db/migrate/20121206133059_create_products.rb
97
+ - spec/dummy/db/migrate/20121210055854_create_product_tech_specs.rb
98
+ - spec/dummy/db/schema.rb
99
+ - spec/dummy/db/seeds.rb
100
+ - spec/dummy/db/test.sqlite3
101
+ - spec/dummy/log/development.log
102
+ - spec/dummy/log/test.log
103
+ - spec/dummy/public/404.html
104
+ - spec/dummy/public/422.html
105
+ - spec/dummy/public/500.html
106
+ - spec/dummy/public/favicon.ico
107
+ - spec/dummy/Rakefile
108
+ - spec/dummy/README.rdoc
109
+ - spec/dummy/script/rails
110
+ - spec/lib/eav_hashes/eav_hash_spec.rb
111
+ - spec/lib/generators/eav_migration_spec.rb
112
+ - spec/spec_helper.rb
113
+ homepage: https://github.com/200proof/eav_hashes
114
+ licenses: []
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ! '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubyforge_project:
133
+ rubygems_version: 1.8.24
134
+ signing_key:
135
+ specification_version: 3
136
+ summary: A developer-friendly implementation of the EAV model for Ruby on Rails.
137
+ test_files:
138
+ - spec/dummy/app/assets/javascripts/application.js
139
+ - spec/dummy/app/assets/stylesheets/application.css
140
+ - spec/dummy/app/controllers/application_controller.rb
141
+ - spec/dummy/app/helpers/application_helper.rb
142
+ - spec/dummy/app/models/custom_test_object.rb
143
+ - spec/dummy/app/models/product.rb
144
+ - spec/dummy/app/views/layouts/application.html.erb
145
+ - spec/dummy/config/application.rb
146
+ - spec/dummy/config/boot.rb
147
+ - spec/dummy/config/database.yml
148
+ - spec/dummy/config/environment.rb
149
+ - spec/dummy/config/environments/development.rb
150
+ - spec/dummy/config/environments/production.rb
151
+ - spec/dummy/config/environments/test.rb
152
+ - spec/dummy/config/initializers/backtrace_silencers.rb
153
+ - spec/dummy/config/initializers/inflections.rb
154
+ - spec/dummy/config/initializers/mime_types.rb
155
+ - spec/dummy/config/initializers/secret_token.rb
156
+ - spec/dummy/config/initializers/session_store.rb
157
+ - spec/dummy/config/initializers/wrap_parameters.rb
158
+ - spec/dummy/config/locales/en.yml
159
+ - spec/dummy/config/routes.rb
160
+ - spec/dummy/config.ru
161
+ - spec/dummy/db/development.sqlite3
162
+ - spec/dummy/db/migrate/20121206133059_create_products.rb
163
+ - spec/dummy/db/migrate/20121210055854_create_product_tech_specs.rb
164
+ - spec/dummy/db/schema.rb
165
+ - spec/dummy/db/seeds.rb
166
+ - spec/dummy/db/test.sqlite3
167
+ - spec/dummy/log/development.log
168
+ - spec/dummy/log/test.log
169
+ - spec/dummy/public/404.html
170
+ - spec/dummy/public/422.html
171
+ - spec/dummy/public/500.html
172
+ - spec/dummy/public/favicon.ico
173
+ - spec/dummy/Rakefile
174
+ - spec/dummy/README.rdoc
175
+ - spec/dummy/script/rails
176
+ - spec/lib/eav_hashes/eav_hash_spec.rb
177
+ - spec/lib/generators/eav_migration_spec.rb
178
+ - spec/spec_helper.rb