datts_right 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- datts_right (0.0.7)
4
+ datts_right (0.0.8)
5
5
  datts_right
6
6
  rails (>= 3.0.0)
7
7
 
data/README.textile CHANGED
@@ -11,8 +11,8 @@ h2. Why make this?
11
11
  # I needed to allow users to create their own dynamic attributes on certain records. I was already running PostgreSQL. My database and code was designed largely on relational structures. I was thinking of moving to MongoDB but saw that I'd pretty much have to rewrite all the models. Creating this gem was the first step to using dynamic attributes on my app.
12
12
  # The "available":http://codaset.com/joelmoss/dynamic-attributes "plugins":https://github.com/moiristo/dynamic_attributes out there that did something like this stuffed the dynamic attributes in a column in the model that had dynamic attributes. Because of this, you:
13
13
  ** Could not order things by dynamic columns straight with SQL
14
- ** Could not (as far as I know) chain scopes, like so: @MyModel.where(:name_which_is_a_real_attribute => "Joe").where_datt(:phone_which_is_dynamic => "23218793")@
15
- ** Could not find by dynamic attribute straight with SQL, like so: @MyModel.find_by_datt_phone_which_is_dynamic("2398291308")@
14
+ ** Could not (as far as I know) chain scopes, like so: @MyModel.where(:name_which_is_a_real_attribute => "Joe").where_dynamic_attribute(:phone_which_is_dynamic => "23218793")@
15
+ ** Could not find by dynamic attribute straight with SQL, like so: @MyModel.find_by_dynamic_attribute_phone_which_is_dynamic("2398291308")@
16
16
  ** Had to add migrations to each model that you wanted to have dynamic attributes
17
17
 
18
18
  h2. Installation
@@ -22,7 +22,7 @@ Create a migration:
22
22
  <pre>
23
23
  class CreateDatts < ActiveRecord::Migration
24
24
  def self.up
25
- create_table(:datts) do |t|
25
+ create_table(:dynamic_attributes) do |t|
26
26
  t.string :name, :null => false
27
27
  t.string :attr_key, :null => false
28
28
  t.string :object_type, :null => false
@@ -33,17 +33,17 @@ class CreateDatts < ActiveRecord::Migration
33
33
  end
34
34
  end
35
35
 
36
- add_index "datts", ["attributable_id"], :name => "index_datts_on_attributable_id"
37
- add_index "datts", ["attributable_type"], :name => "index_datts_on_attributable_type"
38
- add_index "datts", ["attr_key"], :name => "index_datts_on_attr_key"
36
+ add_index "dynamic_attributes", ["attributable_id"], :name => "index_dynamic_attributes_on_attributable_id"
37
+ add_index "dynamic_attributes", ["attributable_type"], :name => "index_dynamic_attributes_on_attributable_type"
38
+ add_index "dynamic_attributes", ["attr_key"], :name => "index_dynamic_attributes_on_attr_key"
39
39
  end
40
40
 
41
41
  def self.down
42
- remove_index "datts", :name => "index_datts_on_attr_key"
43
- remove_index "datts", :name => "index_datts_on_attributable_type"
44
- remove_index "datts", :name => "index_datts_on_attributable_id"
42
+ remove_index "dynamic_attributes", :name => "index_dynamic_attributes_on_attr_key"
43
+ remove_index "dynamic_attributes", :name => "index_dynamic_attributes_on_attributable_type"
44
+ remove_index "dynamic_attributes", :name => "index_dynamic_attributes_on_attributable_id"
45
45
 
46
- drop_table(:datts)
46
+ drop_table(:dynamic_attributes)
47
47
  end
48
48
  end
49
49
  </pre>
@@ -60,7 +60,7 @@ Add this to your Gemfile:
60
60
 
61
61
  Add this to the model that you want to have dynamic attributes:
62
62
 
63
- @has_datts@
63
+ @has_dynamic_attributes@
64
64
 
65
65
  h2. Usage
66
66
 
@@ -96,28 +96,28 @@ Returns true or false
96
96
 
97
97
  h3. Dynamic find
98
98
 
99
- pre. User.find_by_datt_age(240) # returns the first user with that age
99
+ pre. User.find_by_dynamic_attribute_age(240) # returns the first user with that age
100
100
 
101
101
  You can also use:
102
102
 
103
- pre. find_all_by_datt
104
- find_last_by_datt
103
+ pre. find_all_by_dynamic_attribute
104
+ find_last_by_dynamic_attribute
105
105
 
106
106
  h2. Stuff that make things faster
107
107
 
108
108
  The dynamic attributes are only actually saved when save is called on the record that has them.
109
109
 
110
- pre. @user.add_dynamic_attribute(:gunslinger, "boolean") # a column is already written on the "datts" table, with a null value.
111
- @user.add_dynamic_attribute(:middle_name, "string") # a column is already written on the "datts" table, with a null value.
110
+ pre. @user.add_dynamic_attribute(:gunslinger, "boolean") # a column is already written on the "dynamic_attributes" table, with a null value.
111
+ @user.add_dynamic_attribute(:middle_name, "string") # a column is already written on the "dynamic_attributes" table, with a null value.
112
112
  @user.gunslinger = true # saves into memory
113
113
  @user.middle_name = "Unknown" # saves into memory
114
- @user.save # the respective dynamic attribute columns are written in the datts table
114
+ @user.save # the respective dynamic attribute columns are written in the dynamic_attributes table
115
115
 
116
- h2. Structure of the datts table
116
+ h2. Structure of the dynamic_attributes table
117
117
 
118
- Although you probably shouldn't work with it directly, the datts table looks like this:
118
+ Although you probably shouldn't work with it directly, the dynamic_attributes table looks like this:
119
119
 
120
- pre. ActiveRecord::Base.connection.create_table(:datts) do |t|
120
+ pre. ActiveRecord::Base.connection.create_table(:dynamic_attributes) do |t|
121
121
  t.string :name, :null => false
122
122
  t.string :attr_key, :null => false
123
123
  t.string :object_type, :null => false
@@ -128,10 +128,10 @@ pre. ActiveRecord::Base.connection.create_table(:datts) do |t|
128
128
  end
129
129
  end
130
130
 
131
- This means that depending on the type of dynamic attribute you're creating, things will get saved in the respective column in the datts table.
131
+ This means that depending on the type of dynamic attribute you're creating, things will get saved in the respective column in the dynamic_attributes table.
132
132
 
133
133
  pre. @user.add_dynamic_attribute(:gunslinger, "boolean")
134
- adds this to the datts table:
134
+ adds this to the dynamic_attributes table:
135
135
 
136
136
  pre. {
137
137
  :attr_key => "gunslinger",
@@ -172,7 +172,7 @@ h2. Ordering
172
172
 
173
173
  You can call
174
174
 
175
- pre. Product.order_datt("price", "float") # returns all users with their dynamic attribute "name" in ascending order
175
+ pre. Product.order_dynamic_attribute("price", "float") # returns all users with their dynamic attribute "name" in ascending order
176
176
 
177
177
  Why pass the "float" in the order method? Because what if 2 different user records both have the dynamic attribute "price", but for one it's a float, and for the other it's an integer? How would you know which to order things by?
178
178
 
@@ -180,17 +180,17 @@ h2. Where
180
180
 
181
181
  You can do:
182
182
 
183
- pre. Product.where_datt(:price => 200.0, :rating => 5)
183
+ pre. Product.where_dynamic_attribute(:price => 200.0, :rating => 5)
184
184
 
185
185
  As of now it accepts a hash only. If you want to scope to normal attributes, use the normal @where@ method.
186
186
 
187
- h2. Contributing to datts_right
187
+ h2. Contributing to dynamic_attributes_right
188
188
 
189
189
  There are definitely things that don't work, and could be done better. For example, it would be nice to:
190
190
 
191
- # Do away with the special scopes, such as @where_datt@ and @order_datt@. I've tried to override ActiveRecord to make the normal @where@ and @order@ methods to see if the attributes being passed were dynamic, and do the changes necessary to the resulting SQL, but my head "started to hurt":http://stackoverflow.com/q/5590191/61018.
191
+ # Do away with the special scopes, such as @where_dynamic_attribute@ and @order_dynamic_attribute@. I've tried to override ActiveRecord to make the normal @where@ and @order@ methods to see if the attributes being passed were dynamic, and do the changes necessary to the resulting SQL, but my head "started to hurt":http://stackoverflow.com/q/5590191/61018.
192
192
  # Have smarter caching, so that finds with dynamic attributes aren't very expensive.
193
- # Have configurable "datts" table
193
+ # Have configurable "dynamic_attributes" table
194
194
 
195
195
  Warning: the code is full of comments because I needed to visualize the code running.
196
196
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.7
1
+ 0.0.8
data/datts_right.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{datts_right}
8
- s.version = "0.0.7"
8
+ s.version = "0.0.8"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Ramon Tayag"]
@@ -29,14 +29,13 @@ Gem::Specification.new do |s|
29
29
  "VERSION",
30
30
  "datts_right.gemspec",
31
31
  "lib/datts_right.rb",
32
- "lib/datts_right/datt.rb",
32
+ "lib/datts_right/dynamic_attribute.rb",
33
33
  "lib/datts_right/exceptions.rb",
34
34
  "lib/datts_right/instance_methods.rb",
35
35
  "lib/datts_right/page.rb",
36
36
  "lib/datts_right/query_methods.rb",
37
37
  "spec/datt_spec.rb",
38
38
  "spec/datts_right_spec.rb",
39
- "spec/has_datts_migration_generator_spec.rb",
40
39
  "spec/spec_helper.rb"
41
40
  ]
42
41
  s.homepage = %q{http://github.com/ramontayag/datts_right}
@@ -47,7 +46,6 @@ Gem::Specification.new do |s|
47
46
  s.test_files = [
48
47
  "spec/datt_spec.rb",
49
48
  "spec/datts_right_spec.rb",
50
- "spec/has_datts_migration_generator_spec.rb",
51
49
  "spec/spec_helper.rb"
52
50
  ]
53
51
 
@@ -166,6 +164,12 @@ Gem::Specification.new do |s|
166
164
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
167
165
  s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
168
166
  s.add_development_dependency(%q<rcov>, [">= 0"])
167
+ s.add_development_dependency(%q<autotest>, [">= 0"])
168
+ s.add_development_dependency(%q<sqlite3>, [">= 0"])
169
+ s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
170
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
171
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
172
+ s.add_development_dependency(%q<rcov>, [">= 0"])
169
173
  else
170
174
  s.add_dependency(%q<datts_right>, [">= 0"])
171
175
  s.add_dependency(%q<rails>, [">= 3.0.0"])
@@ -278,6 +282,12 @@ Gem::Specification.new do |s|
278
282
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
279
283
  s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
280
284
  s.add_dependency(%q<rcov>, [">= 0"])
285
+ s.add_dependency(%q<autotest>, [">= 0"])
286
+ s.add_dependency(%q<sqlite3>, [">= 0"])
287
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
288
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
289
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
290
+ s.add_dependency(%q<rcov>, [">= 0"])
281
291
  end
282
292
  else
283
293
  s.add_dependency(%q<datts_right>, [">= 0"])
@@ -391,6 +401,12 @@ Gem::Specification.new do |s|
391
401
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
392
402
  s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
393
403
  s.add_dependency(%q<rcov>, [">= 0"])
404
+ s.add_dependency(%q<autotest>, [">= 0"])
405
+ s.add_dependency(%q<sqlite3>, [">= 0"])
406
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
407
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
408
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
409
+ s.add_dependency(%q<rcov>, [">= 0"])
394
410
  end
395
411
  end
396
412
 
data/lib/datts_right.rb CHANGED
@@ -1,45 +1,47 @@
1
1
  require 'datts_right/instance_methods'
2
- require 'datts_right/datt'
3
- #require 'datts_right/query_methods'
4
- #require 'datts_right/exceptions'
2
+ require 'datts_right/dynamic_attribute'
5
3
 
6
4
  module DattsRight
7
- def has_datts(options={})
5
+ def has_dynamic_attributes(options={})
8
6
  include DattsRight::InstanceMethods
9
7
  #include DattsRight::QueryMethods
10
8
  #ActiveRecord::QueryMethods.extend DattsRight::QueryMethods
11
9
  #include DattsRight::Exceptions
12
10
 
13
- cattr_accessor :datts_options
14
- self.datts_options = options
11
+ cattr_accessor :dynamic_attributes_options
12
+ self.dynamic_attributes_options = options
15
13
 
16
- has_many :datts, :as => :attributable, :dependent => :destroy
14
+ has_many :dynamic_attributes, :as => :attributable, :dependent => :destroy
17
15
 
18
16
  # Carry out delayed actions before save
19
17
  before_save :build_dynamic_attributes
20
18
 
21
- # scope :scope_self when looking through attributes so we don't look through all datts
19
+ # scope :scope_self when looking through attributes so we don't look through all dynamic_attributes
22
20
  # Why? What if you have Friend and Page models.
23
- # * Some Phone records have a datt :price
24
- # * Some Page records have a datt :price
21
+ # * Some Phone records have a dynamic_attribute :price
22
+ # * Some Page records have a dynamic_attribute :price
25
23
  #
26
- # When we do Page.find_by_price(400) we want to search only the datts that belong to Page
27
- # and we want to disregard the rest of the datts.
28
- scope :scope_self, lambda { joins(:datts).where("datts.attributable_type = :klass", :klass => self.name) }
29
- scope :dattr_key, lambda { |attr_key| scope_self.joins(:datts).where("datts.attr_key = :attr_key", :attr_key => attr_key)}
30
- scope :dattr_type, lambda { |object_type| scope_self.joins(:datts).where("object_type = :object_type", :object_type => object_type) }
24
+ # When we do Page.find_by_price(400) we want to search only the dynamic_attributes that belong to Page
25
+ # and we want to disregard the rest of the dynamic_attributes.
26
+ scope :scope_self, lambda { joins(:dynamic_attributes).where("dynamic_attributes.attributable_type = :klass", :klass => self.name) }
27
+ scope :with_datt_key, lambda { |args| with_dynamic_attribute_key(args) }
28
+ scope :with_dynamic_attribute_key, lambda { |datt_key| scope_self.joins(:dynamic_attributes).where("dynamic_attributes.attr_key = :datt_key", :datt_key => datt_key)}
29
+ scope :with_datt_type, lambda { |args| with_dynamic_attribute_type(args) }
30
+ scope :with_dynamic_attribute_type, lambda { |object_type| scope_self.joins(:dynamic_attributes).where("object_type = :object_type", :object_type => object_type) }
31
31
 
32
- scope :order_datt, lambda { |attr_key_with_order, object_type|
32
+ scope :order_by_datt, lambda { |attr_key_with_order, object_type| order_by_dynamic_attribute(attr_key_with_order, object_type) }
33
+ scope :order_by_dynamic_attribute, lambda { |attr_key_with_order, object_type|
33
34
  # possible attr_key_with_order forms: "field_name", "field_name ASC", "field_name DESC"
34
35
  split_attr_key_with_order = attr_key_with_order.split(" ")
35
36
  attr_key = split_attr_key_with_order.first
36
37
  order_by = split_attr_key_with_order.last if split_attr_key_with_order.size > 1
37
- order_value = "datts.#{object_type}_value"
38
+ order_value = "dynamic_attributes.#{object_type}_value"
38
39
  order_value << " #{order_by}" if order_by
39
- scope_self.dattr_key(attr_key).joins(:datts).dattr_type(object_type).order(order_value)
40
+ scope_self.with_dynamic_attribute_key(attr_key).joins(:dynamic_attributes).with_dynamic_attribute_type(object_type).order(order_value)
40
41
  }
41
42
 
42
- scope :where_datt, lambda { |opts|
43
+ scope :where_datt, lambda { |opts| where_dynamic_attribute(opts) }
44
+ scope :where_dynamic_attribute, lambda { |opts|
43
45
  # TODO accept stuff other than the normal hash
44
46
  # Lifted from AR::Relation#build_where
45
47
  attributes = case opts
@@ -48,18 +50,13 @@ module DattsRight
48
50
  when Hash
49
51
  opts
50
52
  end
51
- results = self#joins(:datts)
52
- # Look for all DattsRight records whose:
53
- # 1. Has all dynamic_attributes
54
- # 2. Those dynamic attributes match there conditions
53
+ results = self
55
54
  attributes.each do |k, v|
56
55
  conditions = "exists (" +
57
- "select 1 from datts datt where " +
58
- # restricting the attributable_id to pages.id forces all the exists clauses to reference a single attributable record. Layman's terms, assuming Page uses datts_right:
59
- # find only pages that has the matching dynamic attributes
60
- "#{self.table_name}.id = datt.attributable_id " +
61
- "and datt.attributable_type = :attributable_type " +
62
- "and datt.name = :name and datt.#{Datt.attr_column(v)} = :value" +
56
+ "select 1 from dynamic_attributes dynamic_attribute where " +
57
+ "#{self.table_name}.id = dynamic_attribute.attributable_id " +
58
+ "and dynamic_attribute.attributable_type = :attributable_type " +
59
+ "and dynamic_attribute.name = :name and dynamic_attribute.#{DynamicAttribute.attr_column(v)} = :value" +
63
60
  ")"
64
61
  results = results.where(conditions, :attributable_type => self.name, :name => k.to_s, :value => v)
65
62
  end
@@ -71,16 +68,14 @@ module DattsRight
71
68
  begin # Prioritize ActiveRecord's method_missing
72
69
  super(method_id, *arguments)
73
70
  rescue NoMethodError => e
74
- #puts "Method missing: #{method_id}"
75
- if method_id.to_s =~ /^find_(all_|last_)?by_datt_([_a-z]\w*)$/
71
+ if method_id.to_s =~ /^find_(all_|last_)?by_(dynamic_attribute|datt)_([_a-z]\w*)$/
76
72
  all_or_last = $1
77
- attributes = $2.split("_and_")
73
+ attributes = $3.split("_and_")
78
74
  results = self
79
75
  attributes.each_with_index do |attribute, i|
80
- results = results.where_datt(attribute.to_sym => arguments[i])
76
+ results = results.where_dynamic_attribute(attribute.to_sym => arguments[i])
81
77
  end
82
78
 
83
- #puts "this is $1 of the method '#{method_id}': #{all_or_last}."
84
79
  case all_or_last
85
80
  when "all_"
86
81
  results
@@ -94,39 +89,6 @@ module DattsRight
94
89
  else
95
90
  raise e
96
91
  end
97
-
98
- #if method_id.to_s =~ /^find_(all_|last_)by_datt_([_a-z]\w*)$/
99
- #all_or_last = $1
100
- #attributes = $2.split("_and_")
101
- #results = self
102
- #attributes.each_with_index do |attribute, i|
103
- #results = results.where_datt(attribute.to_sym => arguments[i])
104
- #end
105
-
106
- #puts "this is $1 of the method '#{method_id}': #{all_or_last}."
107
- #case all_or_last
108
- #when "all_"
109
- #results
110
- #when "last_"
111
- #results.last
112
- #else
113
- #nil
114
- #end
115
- #elsif method_id.to_s =~ /^find_by_datt_([_a-z]\w*)$/
116
- ##puts "returning a find_by_datt_#{$1}"
117
- #attributes = $1.split("_and_")
118
- ##puts "here are the attributes: #{attributes.inspect}"
119
- #results = self
120
- #attributes.each_with_index do |attribute, i|
121
- ##puts "Adding where_datt(:#{attribute} => #{arguments[i]})"
122
- #results = results.where_datt(attribute.to_sym => arguments[i])
123
- #end
124
-
125
- ##puts "Will return the FIRST of #{results.to_sql}"
126
- #results.first
127
- #else
128
- #nil
129
- #end
130
92
  end
131
93
  end
132
94
 
@@ -147,6 +109,8 @@ module DattsRight
147
109
  super
148
110
  end
149
111
  end
112
+
113
+ alias :has_datts :has_dynamic_attributes
150
114
  end
151
115
 
152
116
  ActiveRecord::Base.extend DattsRight
@@ -1,4 +1,4 @@
1
- class Datt < ActiveRecord::Base
1
+ class DynamicAttribute < ActiveRecord::Base
2
2
  # TODO
3
3
  # Set table name from configuration
4
4
  belongs_to :attributable, :polymorphic => true
@@ -1,15 +1,15 @@
1
1
  module DattsRight
2
2
  module InstanceMethods
3
3
  def add_dynamic_attribute(name, klass)
4
- unless attributes.keys.include?(name.to_s)
5
- name = name.to_s
6
- datt = datts.find_by_attr_key(name.underscore)
7
- unless datt
8
- datt = datts.create :name => name, :attr_key => name.underscore, :object_type => klass
4
+ key = name.to_s
5
+ unless attributes.keys.include?(key)
6
+ dynamic_attribute = dynamic_attributes.find_by_attr_key(key.underscore)
7
+ unless dynamic_attribute
8
+ dynamic_attribute = dynamic_attributes.create :name => key, :attr_key => key.underscore, :object_type => klass
9
9
  dynamic_columns(true)
10
10
  end
11
- #puts "Just added #{name} to #{self.class.name}##{id}, and here are the dynamic_attributes: #{dynamic_columns}"
12
- datt
11
+ #puts "Just added #{key} to #{self.class.name}##{id}, and here are the dynamic_attributes: #{dynamic_columns.inspect}"
12
+ dynamic_attribute
13
13
  else
14
14
  false
15
15
  end
@@ -17,25 +17,26 @@ module DattsRight
17
17
 
18
18
  def remove_dynamic_attribute(name)
19
19
  name = name.to_s
20
- datt = datts.find_by_attr_key(name)
21
- if datt
22
- datt.destroy
20
+ dynamic_attribute = dynamic_attributes.find_by_attr_key(name)
21
+ if dynamic_attribute
22
+ dynamic_attribute.destroy
23
23
  dynamic_columns(true)
24
24
  end
25
25
  end
26
26
 
27
27
  # Works like ActiveRecord's attributes except it returns dynamic attributes only
28
- def dynamic_attributes(reload=false)
29
- @dynamic_attributes ||= {}
30
- return @dynamic_attributes if !reload
31
- #puts "Reloading dynamic_attributes"
32
- datts.each do |datt|
33
- #puts "Adding this to @dynamic_attributes: #{datt.attr_key} => #{datt.value}"
34
- @dynamic_attributes.merge({datt.attr_key => datt.value})
35
- end
36
- #puts "Here are teh datts: #{datts.inspect}, and this is what we're returning: #{@dynamic_attributes}"
37
- @dynamic_attributes.symbolize_keys!
38
- end
28
+ #def dynamic_attributes(reload=false)
29
+ #puts "dynamic_attributes called with reload? #{reload}"
30
+ #@dynamic_attributes ||= {}
31
+ #return @dynamic_attributes if !reload
32
+ ##puts "Reloading dynamic_attributes"
33
+ #dynamic_attributes.each do |dynamic_attribute|
34
+ ##puts "Adding this to @dynamic_attributes: #{dynamic_attribute.attr_key} => #{dynamic_attribute.value}"
35
+ #@dynamic_attributes.merge({dynamic_attribute.attr_key => dynamic_attribute.value})
36
+ #end
37
+ ##puts "Here are teh dynamic_attributes: #{dynamic_attributes.inspect}, and this is what we're returning: #{@dynamic_attributes}"
38
+ #@dynamic_attributes.symbolize_keys!
39
+ #end
39
40
 
40
41
  # Because we cannot determine the difference between the inexistence
41
42
  # between key value pair point to nil (eg :hi => nil) and
@@ -45,18 +46,18 @@ module DattsRight
45
46
  def dynamic_columns(reload=false)
46
47
  @dynamic_columns ||= {}
47
48
  @dynamic_columns if !reload
48
- #puts "Building the dynamic_columns cache, and we'll look through #{datts.count} datts"
49
+ #puts "Building the dynamic_columns cache, and we'll look through #{dynamic_attributes.count} dynamic_attributes"
49
50
  @dynamic_columns={}
50
- datts.reload
51
- datts.each do |datt|
52
- #puts "Going through datt##{datt.id}"
51
+ dynamic_attributes.reload
52
+ dynamic_attributes.each do |dynamic_attribute|
53
+ #puts "Going through dynamic_attribute##{dynamic_attribute.id}"
53
54
  dynamic_column = {
54
- datt.attr_key.to_sym => {
55
- :object_type => datt.object_type,
56
- :value => datt.value
55
+ dynamic_attribute.attr_key.to_sym => {
56
+ :object_type => dynamic_attribute.object_type,
57
+ :value => dynamic_attribute.value
57
58
  }
58
59
  }
59
- #puts "Added #{dynamic_column} to the dynamic columns"
60
+ #puts "Added #{dynamic_column.inspect} to the dynamic columns"
60
61
  @dynamic_columns.merge!(dynamic_column)
61
62
  end
62
63
  #puts "in dynamic_columns, returning: #{@dynamic_columns.inspect}"
@@ -65,7 +66,7 @@ module DattsRight
65
66
 
66
67
  # Determines if the given attribute is a dynamic attribute.
67
68
  def dynamic_attribute?(attr)
68
- #puts "in dynamic_attribute?(:#{attr}). datts: #{datts.inspect}. Datt: #{Datt.all.inspect}"
69
+ #puts "in dynamic_attribute?(:#{attr}). dynamic_attributes: #{dynamic_attributes.inspect}. Datt: #{Datt.all.inspect}"
69
70
  #dynamic_columns.include?(attr.to_s)
70
71
  !dynamic_columns[attr.to_sym].nil?
71
72
  #return dynamic_attributes.include?(attr.to_sym) unless dynamic_attributes.empty?
@@ -94,101 +95,44 @@ module DattsRight
94
95
  #assign_multiparameter_attributes(multi_parameter_attributes)
95
96
  #end
96
97
 
97
- # Overrides AR::Persistence#update_attributes
98
- # Needed to change it because the AR::Persistence method updated the attributes
99
- # method directly.
100
- # Ex.
101
- # self.attributes = attributes
102
- #
103
- # That won't work because our dynamic attributes aren't in the attributes field
104
- def update_attributes(attributes)
98
+ def update_dynamic_attributes(attributes)
105
99
  # The following transaction covers any possible database side-effects of the
106
100
  # attributes assignment. For example, setting the IDs of a child collection.
107
101
  with_transaction_returning_status do
108
- attributes.each do |k, v|
109
- self.send("#{k}=", v)
102
+ attributes.symbolize_keys.each do |k, v|
103
+ self.write_dynamic_attribute(k, v)
110
104
  end
111
105
  save
112
106
  end
113
107
  end
114
108
 
115
- # Overrides AR::Persistence#update_attributes!
116
- # See DattsRight#update_attributes for the reason why
117
- def update_attributes!(attributes)
109
+ def update_dynamic_attributes!(attributes)
118
110
  with_transaction_returning_status do
119
- attributes.each do |k, v|
120
- self.send("#{k}=", v)
111
+ attributes.symbolize_keys.each do |k, v|
112
+ self.write_dynamic_attribute(k, v)
121
113
  end
122
114
  save!
123
115
  end
124
116
  end
125
117
 
126
- private
127
-
128
- # Called after validation on update so that dynamic attributes behave
129
- # like normal attributes in the fact that the database is not touched
130
- # until save is called.
131
- def build_dynamic_attributes
132
- return if @save_dynamic_attr.nil?
133
- # This originally saves things into the "datts" column.
134
- #write_attribute_without_dynamic_attributes "datts", @save_dynamic_attr
135
- # We save things into the datts table
136
- @save_dynamic_attr.each do |k, v|
137
- k = k.to_s
138
- datt = datts.find_by_attr_key(k)
139
- #puts "to create or to update #{k}?"
140
- if datt
141
- datt.update_attribute(:value, v)
142
- #puts "updated: #{datt.inspect}"
143
- #else
144
- #datt = datts.create! :name => k, :attr_key => k, :value => v
145
- #puts "created: #{datt.inspect} among these datts: #{datts.inspect}"
146
- end
147
- end
148
- @save_dynamic_attr = {}
149
- true
150
- end
151
-
152
- # Implements dynamic-attributes as if real getter/setter methods
153
- # were defined.
154
- def method_missing(method_id, *args, &block)
155
- puts "in DattsRight::InstanceMethods#method_missing with method_id #{method_id}"
156
- begin
157
- super method_id, *args, &block
158
- rescue NoMethodError => e
159
- puts "AR doesn't have #{method_id} so DattsRight will take care of it instead"
160
- attr_name = method_id.to_s.sub(/\=$/, '')
161
- #puts "Now we check to see if price is a dynamic attribute. dynamic_columns: #{dynamic_columns}. is #{attr_name} in those dynamic_columns? #{dynamic_attribute?(attr_name)}"
162
- if dynamic_attribute?(attr_name)
163
- #puts "== And #{method_id} is a dynamic method"
164
- if method_id.to_s =~ /\=$/
165
- return write_attribute(attr_name, args[0])
166
- else
167
- return read_attribute(attr_name)
168
- end
169
- end
170
- raise e
171
- end
172
- end
173
-
174
118
  # Overrides AR::Base#read_attribute
175
- def read_attribute(attr_name)
119
+ def read_dynamic_attribute(attr_name)
176
120
  attr_name = attr_name.to_s
177
121
  if dynamic_attribute?(attr_name)
178
- #puts "trying to read datt #{attr_name}"
122
+ #puts "trying to read dynamic_attribute #{attr_name}"
179
123
  # If value is in the @save_dynamic_attr cache, and it's not blank
180
124
  if !@save_dynamic_attr.blank? and @save_dynamic_attr[attr_name]
181
- #puts "datt #{attr_name} IS in cache, so let's return its value"
125
+ #puts "dynamic_attribute #{attr_name} IS in cache, so let's return its value"
182
126
  # Then we return the value
183
127
  return @save_dynamic_attr[attr_name]
184
128
  else # The value is not there, or it's blank
185
- #puts "datt #{attr_name} is NOT in cache, so let's load it from the datt table"
129
+ #puts "dynamic_attribute #{attr_name} is NOT in cache, so let's load it from the dynamic_attribute table"
186
130
  #attrs = read_attribute_without_dynamic_attributes(dynamic_attributes_options[:column_name].to_s)
187
- #puts "Here are ALL the datts: #{Datt.all.inspect} and my id is: #{id}"
188
- #puts "Here are my the datts: #{datts.inspect} and my id is: #{id}. and the first datt's value is #{datts.first.value}"
189
- datt = datts.find_by_attr_key(attr_name)
190
- #puts "This is the dat I find: #{datt.inspect}"
191
- return datt.try(:value)
131
+ #puts "Here are ALL the dynamic_attributes: #{Datt.all.inspect} and my id is: #{id}"
132
+ #puts "Here are my the dynamic_attributes: #{dynamic_attributes.inspect} and my id is: #{id}. and the first dynamic_attribute's value is #{dynamic_attributes.first.value}"
133
+ dynamic_attribute = dynamic_attributes.find_by_attr_key(attr_name)
134
+ #puts "This is the dat I find: #{dynamic_attribute.inspect}"
135
+ return dynamic_attribute.try(:value)
192
136
  #attrs = attrs.nil? ? nil : YAML.load(attrs).symbolize_keys! unless attrs.is_a? Hash
193
137
  #return nil if attrs.blank?
194
138
  #return attrs[attr_name.to_sym]
@@ -199,7 +143,7 @@ module DattsRight
199
143
  end
200
144
 
201
145
  # Overrides AR::Base#write_attribute
202
- def write_attribute(attr_name, value)
146
+ def write_dynamic_attribute(attr_name, value)
203
147
  #puts "attempting to write: #{attr_name} = #{value}"
204
148
  if dynamic_attribute?(attr_name)
205
149
  #puts "#{attr_name} is a dynamic_attribute"
@@ -207,9 +151,62 @@ module DattsRight
207
151
 
208
152
  @save_dynamic_attr ||= {} # create the cache if needed
209
153
  return @save_dynamic_attr[attr_name] = value
154
+ return nil
210
155
  end
211
-
212
- super(attr_name, value)
213
156
  end
157
+
158
+ private
159
+
160
+ # Called after validation on update so that dynamic attributes behave
161
+ # like normal attributes in the fact that the database is not touched
162
+ # until save is called.
163
+ def build_dynamic_attributes
164
+ return if @save_dynamic_attr.nil?
165
+ # This originally saves things into the "dynamic_attributes" column.
166
+ #write_attribute_without_dynamic_attributes "dynamic_attributes", @save_dynamic_attr
167
+ # We save things into the dynamic_attributes table
168
+ @save_dynamic_attr.each do |k, v|
169
+ k = k.to_s
170
+ dynamic_attribute = dynamic_attributes.find_by_attr_key(k)
171
+ #puts "to create or to update #{k}?"
172
+ if dynamic_attribute
173
+ dynamic_attribute.update_attribute(:value, v)
174
+ #puts "updated: #{dynamic_attribute.inspect}"
175
+ #else
176
+ #dynamic_attribute = dynamic_attributes.create! :name => k, :attr_key => k, :value => v
177
+ #puts "created: #{dynamic_attribute.inspect} among these dynamic_attributes: #{dynamic_attributes.inspect}"
178
+ end
179
+ end
180
+ @save_dynamic_attr = {}
181
+ true
182
+ end
183
+
184
+ # Implements dynamic-attributes as if real getter/setter methods
185
+ # were defined.
186
+ #def method_missing(method_id, *args, &block)
187
+ #puts "in DattsRight::InstanceMethods#method_missing with method_id #{method_id}"
188
+ #begin
189
+ #super method_id, *args, &block
190
+ #rescue NoMethodError => e
191
+ #puts "AR doesn't have #{method_id} so DattsRight will take care of it instead"
192
+ #attr_name = method_id.to_s.sub(/\=$/, '')
193
+ ##puts "Now we check to see if price is a dynamic attribute. dynamic_columns: #{dynamic_columns}. is #{attr_name} in those dynamic_columns? #{dynamic_attribute?(attr_name)}"
194
+ #if dynamic_attribute?(attr_name)
195
+ ##puts "== And #{method_id} is a dynamic method"
196
+ #if method_id.to_s =~ /\=$/
197
+ #return write_attribute(attr_name, args[0])
198
+ #else
199
+ #return read_attribute(attr_name)
200
+ #end
201
+ #end
202
+ #raise e
203
+ #end
204
+ #end
205
+
206
+ alias :add_datt :add_dynamic_attribute
207
+ alias :remove_datt :remove_dynamic_attribute
208
+ alias :read_datt :read_dynamic_attribute
209
+ alias :write_datt :write_dynamic_attribute
210
+ alias :update_dynamic_attribute :write_dynamic_attribute
214
211
  end
215
212
  end
@@ -1,3 +1,3 @@
1
1
  class Page < ActiveRecord::Base
2
- has_datts
2
+ has_dynamic_attributes
3
3
  end
data/spec/datt_spec.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
- describe Datt do
3
+ describe DynamicAttribute do
4
4
  before do
5
5
  reset_database
6
6
  @page = Page.create
@@ -8,13 +8,13 @@ describe Datt do
8
8
 
9
9
  it "should allow transferring between String and Text" do
10
10
  @page.add_dynamic_attribute(:foo, "string")
11
- @page.foo = "this is a string"
11
+ @page.write_dynamic_attribute :foo, "this is a string"
12
12
  @page.save
13
- @page.foo = "t"*300
13
+ @page.write_dynamic_attribute :foo, "t"*300
14
14
  @page.save
15
- @page.datts.find_by_attr_key("foo").object_type.should == "text"
16
- @page.foo = "this is a string again"
15
+ @page.dynamic_attributes.find_by_attr_key("foo").object_type.should == "text"
16
+ @page.write_dynamic_attribute :foo, "this is a string again"
17
17
  @page.save
18
- @page.datts.find_by_attr_key("foo").object_type.should == "string"
18
+ @page.dynamic_attributes.find_by_attr_key("foo").object_type.should == "string"
19
19
  end
20
20
  end
@@ -7,9 +7,13 @@ describe DattsRight do
7
7
  end
8
8
 
9
9
  describe ".add_dynamic_attribute(attr_key, object_type)" do
10
+ it "should be aliased by add_datt" do
11
+ Page.instance_method(:add_dynamic_attribute).should == Page.instance_method(:add_datt)
12
+ end
13
+
10
14
  it "should add a dynamic attribute with nil value" do
11
15
  @page.add_dynamic_attribute(:rocks, "string")
12
- @page.dynamic_attributes[:rocks].should be_nil
16
+ @page.dynamic_columns[:rocks][:value].should be_nil
13
17
  end
14
18
 
15
19
  it "should ignore when trying to add same attribute" do
@@ -30,6 +34,10 @@ describe DattsRight do
30
34
  end
31
35
 
32
36
  describe ".remove_dynamic_attribute(attr_key)" do
37
+ it "should be aliased by remove_datt" do
38
+ Page.instance_method(:remove_dynamic_attribute).should == Page.instance_method(:remove_datt)
39
+ end
40
+
33
41
  it "should remove the attribute completely" do
34
42
  @page.add_dynamic_attribute(:rocks, "string")
35
43
  @page.remove_dynamic_attribute(:rocks)
@@ -60,115 +68,129 @@ describe DattsRight do
60
68
 
61
69
  it "should allow saving of integers" do
62
70
  @page.add_dynamic_attribute(:price, "integer")
63
- @page.price = 300
71
+ @page.write_dynamic_attribute :price, 300
64
72
  @page.save
65
73
  @page = Page.last
66
- @page.price.should == 300
74
+ @page.read_dynamic_attribute(:price).should == 300
67
75
  end
68
76
 
69
77
  it "should allow saving of floats" do
70
78
  @page.add_dynamic_attribute(:price, "float")
71
- @page.price = 300.0
79
+ @page.write_dynamic_attribute :price, 300.0
72
80
  @page.save
73
81
  @page = Page.last
74
- @page.price.should == 300.0
82
+ @page.read_dynamic_attribute(:price).should == 300.0
75
83
  end
76
84
 
77
85
  it "should allow saving of true" do
78
86
  @page.add_dynamic_attribute(:real, "boolean")
79
- @page.real = true
87
+ @page.write_dynamic_attribute :real, true
80
88
  @page.save
81
89
  @page = Page.last
82
- @page.real.should be_true
90
+ @page.read_dynamic_attribute(:real).should be_true
83
91
  end
84
92
 
85
93
  it "should allow saving of false" do
86
94
  @page.add_dynamic_attribute(:real, "boolean")
87
- @page.real = false
95
+ @page.write_dynamic_attribute :real, false
88
96
  @page.save
89
97
  @page = Page.last
90
- @page.real.should be_false
98
+ @page.read_dynamic_attribute(:real).should be_false
91
99
  end
92
100
 
93
101
  it "should allow saving of strings" do
94
102
  @page.add_dynamic_attribute(:real, "string")
95
- @page.real = "its real alright"
103
+ @page.write_dynamic_attribute :real, "its real alright"
96
104
  @page.save
97
105
  @page = Page.last
98
- @page.real.should == "its real alright"
106
+ @page.read_dynamic_attribute(:real).should == "its real alright"
99
107
  end
100
108
 
101
109
  it "should allow saving of text" do
102
110
  @page.add_dynamic_attribute(:real, "text")
103
- @page.real = "t"*256
111
+ @page.write_dynamic_attribute :real, "t"*256
104
112
  @page.save
105
113
  @page = Page.last
106
- @page.real.should == "t"*256
114
+ @page.read_dynamic_attribute(:real).should == "t"*256
107
115
  end
108
116
 
109
117
  it "should cache the attribute" do
110
118
  @page.add_dynamic_attribute(:price, "integer")
111
- @page.price = 200
112
- @page.price.should == 200
119
+ @page.write_dynamic_attribute :price, 200
120
+ @page.read_dynamic_attribute(:price).should == 200
113
121
  end
114
122
 
115
123
  it "should not save the attribute if save on the attributable object isn't called" do
116
124
  @page.add_dynamic_attribute(:price, "integer")
117
- @page.price = 200
125
+ @page.write_dynamic_attribute :price, 200
118
126
  @page = Page.last
119
- @page.price.should be_nil
127
+ @page.read_dynamic_attribute(:price).should be_nil
120
128
  end
121
129
 
122
130
  it "should allow overwriting of values" do
123
131
  @page.add_dynamic_attribute(:price, "integer")
124
- @page.price = 200
132
+ @page.write_dynamic_attribute :price, 200
125
133
  @page.save
126
134
  @page = Page.last
127
- @page.price = 300
135
+ @page.write_dynamic_attribute :price, 300
128
136
  @page.save
129
137
  @page = Page.last
130
- @page.price.should == 300
138
+ @page.read_dynamic_attribute(:price).should == 300
131
139
  end
132
140
 
133
141
  it "should allow nullifying of attributes, but keeping the fields there" do
134
142
  @page.add_dynamic_attribute(:farce, "string")
135
- @page.farce = "Nothing here my friend"
143
+ @page.write_dynamic_attribute :farce, "Nothing here my friend"
136
144
  @page.save
137
- @page.farce = nil
145
+ @page.write_dynamic_attribute :farce, nil
138
146
  @page.dynamic_attribute?(:farce).should be_true
139
147
  end
140
148
 
141
- describe "on dynamic find_by_datt methods" do
149
+ describe ".read_dynamic_attribute" do
150
+ it "should be aliased by read_datt" do
151
+ Page.instance_method(:read_dynamic_attribute).should == Page.instance_method(:read_datt)
152
+ end
153
+ end
154
+
155
+ describe "on dynamic find_by_dynamic_attribute methods" do
156
+ it "should be aliased by find_by_datt" do
157
+ @page.add_dynamic_attribute(:price, "integer")
158
+ @page.write_dynamic_attribute :price, 400
159
+ @page.save
160
+ Page.find_by_datt_price(400).should == Page.find_by_dynamic_attribute_price(400)
161
+ end
162
+
142
163
  it "should be able to return single records" do
143
164
  @page.add_dynamic_attribute(:price, "integer")
144
- @page.price = 400
165
+ @page.write_dynamic_attribute :price, 400
145
166
  @page.save
146
167
 
147
168
  @page_2 = Page.create
148
169
  @page_2.add_dynamic_attribute(:price, "integer")
149
- @page_2.price = 500
170
+ @page_2.write_dynamic_attribute :price, 500
150
171
  @page_2.save
151
172
 
152
- Page.find_by_datt_price(400).should == @page
153
- Page.find_by_datt_price(400).should_not == @page_2
173
+ @results = Page.find_by_dynamic_attribute_price(400)
174
+ @results.should == @page
175
+ @results.should_not == @page_2
154
176
  end
155
177
 
156
178
  it "should be able to return all matching records" do
157
179
  @page.add_dynamic_attribute(:price, "integer")
158
- @page.price = 400
180
+ @page.write_dynamic_attribute :price, 400
159
181
  @page.save
160
182
 
161
183
  @page_2 = Page.create
162
184
  @page_2.add_dynamic_attribute(:price, "integer")
163
- @page_2.price = 500
185
+ @page_2.write_dynamic_attribute :price, 500
164
186
  @page_2.save
165
187
 
166
188
  @page_3 = Page.create
167
189
  @page_3.add_dynamic_attribute(:price, "integer")
168
- @page_3.price = 400
190
+ @page_3.write_dynamic_attribute :price, 400
169
191
  @page_3.save
170
192
 
171
- @results = Page.find_all_by_datt_price(400)
193
+ @results = Page.find_all_by_dynamic_attribute_price(400)
172
194
  @results.should include(@page)
173
195
  @results.should_not include(@page_2)
174
196
  @results.should include(@page_3)
@@ -180,15 +202,15 @@ describe DattsRight do
180
202
 
181
203
  it "should be able to return the last record" do
182
204
  @page.add_dynamic_attribute(:price, "integer")
183
- @page.price = 400
205
+ @page.write_dynamic_attribute :price, 400
184
206
  @page.save
185
207
 
186
208
  @page_2 = Page.create
187
209
  @page_2.add_dynamic_attribute(:price, "integer")
188
- @page_2.price = 400
210
+ @page_2.write_dynamic_attribute :price, 400
189
211
  @page_2.save
190
212
 
191
- Page.find_last_by_datt_price(400) == @page_2
213
+ Page.find_last_by_dynamic_attribute_price(400) == @page_2
192
214
  end
193
215
 
194
216
  it "should allow normal attributes to work" do
@@ -201,15 +223,15 @@ describe DattsRight do
201
223
  it "should allow chaining" do
202
224
  @page.add_dynamic_attribute(:price, "integer")
203
225
  @page.name = "fixed"
204
- @page.price = 400
226
+ @page.write_dynamic_attribute :price, 400
205
227
  @page.save
206
228
 
207
229
  @page_2 = Page.create
208
230
  @page_2.add_dynamic_attribute(:price, "integer")
209
- @page_2.price = 500
231
+ @page_2.write_dynamic_attribute :price, 500
210
232
  @page_2.save
211
233
 
212
- @pages = Page.where(:name => "fixed").find_by_datt_price(400)
234
+ @pages = Page.where(:name => "fixed").find_by_dynamic_attribute_price(400)
213
235
  @pages.should == @page
214
236
  @pages.should_not == @page_2
215
237
  end
@@ -217,19 +239,19 @@ describe DattsRight do
217
239
 
218
240
  it "should allow multiple attributes" do
219
241
  @page.add_dynamic_attribute(:price, "integer")
220
- @page.price = 400
242
+ @page.write_dynamic_attribute :price, 400
221
243
  @page.add_dynamic_attribute(:farce, "string")
222
- @page.farce = "hitt"
244
+ @page.write_dynamic_attribute :farce, "hitt"
223
245
  @page.save
224
246
 
225
247
  @page_2 = Page.create
226
248
  @page_2.add_dynamic_attribute(:price, "integer")
227
- @page_2.price = 400
249
+ @page_2.write_dynamic_attribute :price, 400
228
250
  @page_2.add_dynamic_attribute(:farce, "string")
229
- @page_2.farce = "hi"
251
+ @page_2.write_dynamic_attribute :farce, "hi"
230
252
  @page_2.save
231
253
 
232
- @pages = Page.find_by_datt_price_and_farce(400, "hi")
254
+ @pages = Page.find_by_dynamic_attribute_price_and_farce(400, "hi")
233
255
  @pages.should == @page_2
234
256
  @pages.should_not == @page
235
257
  end
@@ -240,83 +262,116 @@ describe DattsRight do
240
262
  end
241
263
 
242
264
  it "should not save the value" do
243
- @page.price = 200
265
+ @page.write_dynamic_attribute :price, 200
244
266
  @page.save
245
- @page.price = "hi there"
267
+ @page.write_dynamic_attribute :price, "hi there"
246
268
  @page.save
247
- Page.last.price.should == 200
269
+ Page.last.read_dynamic_attribute(:price).should == 200
248
270
  end
249
271
  end
250
272
 
251
273
  it "should allow mass assignment" do
252
274
  @page.add_dynamic_attribute(:price, "integer")
253
275
  @page.add_dynamic_attribute(:farce, "string")
254
- @page.update_attributes(:price => 200, :farce => "hi")
255
- @page.price.should == 200
256
- @page.farce.should == "hi"
276
+ @page.update_dynamic_attributes(:price => 200, :farce => "hi")
277
+ @page.read_dynamic_attribute(:price).should == 200
278
+ @page.read_dynamic_attribute(:farce).should == "hi"
257
279
 
258
- @page.update_attributes!(:price => 300, :farce => "not farce!")
259
- @page.price.should == 300
260
- @page.farce.should == "not farce!"
280
+ @page.update_dynamic_attributes!(:price => 300, :farce => "not farce!")
281
+ @page.read_dynamic_attribute(:price).should == 300
282
+ @page.read_dynamic_attribute(:farce).should == "not farce!"
261
283
  end
262
284
 
263
- it "should allow use of update_attribute" do
285
+ it "should allow use of update_dynamic_attribute" do
264
286
  @page.add_dynamic_attribute(:price, "integer")
265
- @page.update_attribute(:price, 200)
266
- @page.price.should == 200
287
+ @page.update_dynamic_attribute(:price, 200)
288
+ @page.read_dynamic_attribute(:price).should == 200
267
289
  end
268
290
 
269
- describe "ordering" do
291
+ describe "order_by_dynamic_attribute" do
292
+ it "should be aliased by order_by_datt" do
293
+ @page.add_dynamic_attribute(:price, "integer")
294
+ @page.write_dynamic_attribute :price, 2
295
+ @page.save
296
+ Page.order_by_dynamic_attribute("price", "integer").should == Page.order_by_datt("price", "integer")
297
+ end
298
+
270
299
  it "should default to asc" do
271
300
  @page.add_dynamic_attribute(:price, "integer")
272
- @page.price = 2
301
+ @page.write_dynamic_attribute :price, 2
273
302
  @page.save
274
303
  @page_2 = Page.create
275
304
  @page_2.add_dynamic_attribute(:price, "integer")
276
- @page_2.price = 1
305
+ @page_2.write_dynamic_attribute :price, 1
277
306
  @page_2.save
278
307
  @page_3 = Page.create
279
308
  @page_3.add_dynamic_attribute(:price, "float")
280
- @page_3.price = 3.0
309
+ @page_3.write_dynamic_attribute :price, 3.0
281
310
  @page_3.save
282
311
  @page_4 = Page.create
283
312
  @page_4.add_dynamic_attribute(:price, "float")
284
- @page_4.price = 3.5
313
+ @page_4.write_dynamic_attribute :price, 3.5
285
314
  @page_4.save
286
315
 
287
316
  # What if different records have price but they are of different object_type?
288
- # page_1.price is an "integer" and it's saved in "integer_value" column
289
- # page_2.price is a "float" and it's saved in "float_value"
317
+ # page_1.read_dynamic_attribute(:price) is an "integer" and it's saved in "integer_value" column
318
+ # page_2.read_dynamic_attribute(:price) is a "float" and it's saved in "float_value"
290
319
  #
291
- # How would you work on Page.order_datt("price")?
320
+ # How would you work on Page.order_by_dynamic_attribute("price")?
292
321
  #
293
322
  # Answer 1: we could require passing of the object_type in the order method
294
- # This way, we know which column to look at => order_datt("price", "integer")
295
- Page.order_datt("price", "integer").should == [@page_2, @page]
296
- Page.order_datt("price DESC", "float").should == [@page_4, @page_3]
323
+ # This way, we know which column to look at => order_by_dynamic_attribute("price", "integer")
324
+ Page.order_by_dynamic_attribute("price", "integer").should == [@page_2, @page]
325
+ Page.order_by_dynamic_attribute("price DESC", "float").should == [@page_4, @page_3]
297
326
  end
298
327
  end
299
328
 
300
- describe "where_datt" do
301
- it "should automatically join in the datts table" do
329
+ describe ".write_dynamic_attribute" do
330
+ it "should be aliased by write_datt" do
331
+ Page.instance_method(:write_dynamic_attribute).should == Page.instance_method(:write_datt)
332
+ end
333
+ end
334
+
335
+ describe ".with_dynamic_attribute_key" do
336
+ it "should be aliased by .with_datt_key" do
337
+ @page.add_dynamic_attribute(:price, "float")
338
+ Page.with_dynamic_attribute_key(:price).should == Page.with_datt_key(:price)
339
+ end
340
+ end
341
+
342
+ describe ".with_dynamic_attribute_type" do
343
+ it "should be aliased by .with_datt_type" do
344
+ @page.add_dynamic_attribute(:price, "float")
345
+ Page.with_dynamic_attribute_type("float").should == Page.with_datt_type("float")
346
+ end
347
+ end
348
+
349
+ describe "where_dynamic_attribute" do
350
+ it "should be aliased by where_datt" do
351
+ @page.add_dynamic_attribute(:price, "float")
352
+ @page.write_dynamic_attribute :price, 200.0
353
+ Page.where_dynamic_attribute(:price => 200.0).should == Page.where_datt(:price => 200.0)
354
+ end
355
+
356
+ it "should automatically join in the dynamic_attributes table" do
302
357
  @page.add_dynamic_attribute(:price, "float")
303
- @page.price = 200.0
358
+ @page.write_dynamic_attribute :price, 200.0
304
359
  @page.add_dynamic_attribute(:farce, "boolean")
305
- @page.farce = true
360
+ @page.write_dynamic_attribute :farce, true
306
361
  @page.save
307
362
 
308
363
  @page_2 = Page.create
309
364
  @page_2.add_dynamic_attribute(:price, "integer")
310
365
  @page_2.add_dynamic_attribute(:farce, "boolean")
311
- @page_2.farce = true
312
- @page_2.price = 1
366
+ @page_2.write_dynamic_attribute :farce, true
367
+ @page_2.write_dynamic_attribute :price, 1
313
368
  @page_2.save
314
369
 
315
- @result = Page.where_datt(:price => 200.0, :farce => true)
370
+ @result = Page.where_dynamic_attribute(:price => 200.0, :farce => true)
316
371
  @result.should include(@page)
317
372
  @result.should_not include(@page_2)
318
373
 
319
- #@result = Page.where_datt("price < :price", :price => 199.0)
374
+ #@result = Page.where_dynamic_attribute("price < :price", :price => 199.0)
320
375
  #@result.should_not include(@page)
321
376
  #@result.should include(@page_2)
322
377
  end
@@ -324,21 +379,21 @@ describe DattsRight do
324
379
  it "should allow chaining with where scopes" do
325
380
  @page.add_dynamic_attribute(:price, "integer")
326
381
  @page.name = "aardvark"
327
- @page.price = 200
382
+ @page.write_dynamic_attribute :price, 200
328
383
  @page.save
329
384
 
330
385
  @page_2 = Page.create
331
386
  @page_2.add_dynamic_attribute(:price, "integer")
332
- @page_2.price = 200
387
+ @page_2.write_dynamic_attribute :price, 200
333
388
  @page_2.save
334
389
 
335
- @results = Page.where_datt(:price => 200).where(:name => "aardvark")
390
+ @results = Page.where_dynamic_attribute(:price => 200).where(:name => "aardvark")
336
391
  @results.should include(@page)
337
392
  @results.should_not include(@page_2)
338
393
  end
339
394
 
340
395
  it "should return an empty array if we're looking for a field that doesn't exist" do
341
- Page.where_datt(:bogus_field => "none").should be_empty
396
+ Page.where_dynamic_attribute(:bogus_field => "none").should be_empty
342
397
  end
343
398
  end
344
399
  end
data/spec/spec_helper.rb CHANGED
@@ -4,7 +4,7 @@ require 'rubygems'
4
4
  require 'active_record'
5
5
  require 'rspec'
6
6
  require 'datts_right'
7
- require 'datts_right/page' # for testing
7
+ require 'datts_right/page'
8
8
 
9
9
  # Allow to connect to SQLite
10
10
  root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
@@ -23,13 +23,13 @@ RSpec.configure do |config|
23
23
  end
24
24
 
25
25
  def reset_database
26
- %W(pages datts).each do |table_name|
26
+ %W(pages dynamic_attributes).each do |table_name|
27
27
  ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS '#{table_name}'")
28
28
  end
29
29
  ActiveRecord::Base.connection.create_table(:pages) do |t|
30
30
  t.string :name, :default => "My name"
31
31
  end
32
- ActiveRecord::Base.connection.create_table(:datts) do |t|
32
+ ActiveRecord::Base.connection.create_table(:dynamic_attributes) do |t|
33
33
  t.string :name, :null => false
34
34
  t.string :attr_key, :null => false
35
35
  t.string :object_type, :null => false
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datts_right
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 15
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 7
10
- version: 0.0.7
9
+ - 8
10
+ version: 0.0.8
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ramon Tayag
@@ -1684,6 +1684,96 @@ dependencies:
1684
1684
  name: rcov
1685
1685
  version_requirements: *id111
1686
1686
  prerelease: false
1687
+ - !ruby/object:Gem::Dependency
1688
+ type: :development
1689
+ requirement: &id112 !ruby/object:Gem::Requirement
1690
+ none: false
1691
+ requirements:
1692
+ - - ">="
1693
+ - !ruby/object:Gem::Version
1694
+ hash: 3
1695
+ segments:
1696
+ - 0
1697
+ version: "0"
1698
+ name: autotest
1699
+ version_requirements: *id112
1700
+ prerelease: false
1701
+ - !ruby/object:Gem::Dependency
1702
+ type: :development
1703
+ requirement: &id113 !ruby/object:Gem::Requirement
1704
+ none: false
1705
+ requirements:
1706
+ - - ">="
1707
+ - !ruby/object:Gem::Version
1708
+ hash: 3
1709
+ segments:
1710
+ - 0
1711
+ version: "0"
1712
+ name: sqlite3
1713
+ version_requirements: *id113
1714
+ prerelease: false
1715
+ - !ruby/object:Gem::Dependency
1716
+ type: :development
1717
+ requirement: &id114 !ruby/object:Gem::Requirement
1718
+ none: false
1719
+ requirements:
1720
+ - - ~>
1721
+ - !ruby/object:Gem::Version
1722
+ hash: 3
1723
+ segments:
1724
+ - 2
1725
+ - 3
1726
+ - 0
1727
+ version: 2.3.0
1728
+ name: rspec
1729
+ version_requirements: *id114
1730
+ prerelease: false
1731
+ - !ruby/object:Gem::Dependency
1732
+ type: :development
1733
+ requirement: &id115 !ruby/object:Gem::Requirement
1734
+ none: false
1735
+ requirements:
1736
+ - - ~>
1737
+ - !ruby/object:Gem::Version
1738
+ hash: 23
1739
+ segments:
1740
+ - 1
1741
+ - 0
1742
+ - 0
1743
+ version: 1.0.0
1744
+ name: bundler
1745
+ version_requirements: *id115
1746
+ prerelease: false
1747
+ - !ruby/object:Gem::Dependency
1748
+ type: :development
1749
+ requirement: &id116 !ruby/object:Gem::Requirement
1750
+ none: false
1751
+ requirements:
1752
+ - - ~>
1753
+ - !ruby/object:Gem::Version
1754
+ hash: 7
1755
+ segments:
1756
+ - 1
1757
+ - 5
1758
+ - 2
1759
+ version: 1.5.2
1760
+ name: jeweler
1761
+ version_requirements: *id116
1762
+ prerelease: false
1763
+ - !ruby/object:Gem::Dependency
1764
+ type: :development
1765
+ requirement: &id117 !ruby/object:Gem::Requirement
1766
+ none: false
1767
+ requirements:
1768
+ - - ">="
1769
+ - !ruby/object:Gem::Version
1770
+ hash: 3
1771
+ segments:
1772
+ - 0
1773
+ version: "0"
1774
+ name: rcov
1775
+ version_requirements: *id117
1776
+ prerelease: false
1687
1777
  description: Creates a separate table that saves all your dynamic attributes.
1688
1778
  email: ramon@tayag.net
1689
1779
  executables: []
@@ -1706,14 +1796,13 @@ files:
1706
1796
  - VERSION
1707
1797
  - datts_right.gemspec
1708
1798
  - lib/datts_right.rb
1709
- - lib/datts_right/datt.rb
1799
+ - lib/datts_right/dynamic_attribute.rb
1710
1800
  - lib/datts_right/exceptions.rb
1711
1801
  - lib/datts_right/instance_methods.rb
1712
1802
  - lib/datts_right/page.rb
1713
1803
  - lib/datts_right/query_methods.rb
1714
1804
  - spec/datt_spec.rb
1715
1805
  - spec/datts_right_spec.rb
1716
- - spec/has_datts_migration_generator_spec.rb
1717
1806
  - spec/spec_helper.rb
1718
1807
  has_rdoc: true
1719
1808
  homepage: http://github.com/ramontayag/datts_right
@@ -1752,5 +1841,4 @@ summary: Allows saving of dynamic attributes in your ActiveRecord model
1752
1841
  test_files:
1753
1842
  - spec/datt_spec.rb
1754
1843
  - spec/datts_right_spec.rb
1755
- - spec/has_datts_migration_generator_spec.rb
1756
1844
  - spec/spec_helper.rb
@@ -1,13 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- #describe "Migration Generator" do
4
- #before do
5
- #Rails.stub!(:version).and_return("3.0.0")
6
- #Dir.mkdir("#{RAILS_ROOT}/db") unless File.exists?("#{RAILS_ROOT}/db")
7
- #Dir.mkdir("#{RAILS_ROOT}/db/migrate") unless File.exists?("#{RAILS_ROOT}/db/migrate")
8
- #end
9
-
10
- #it "should generate migration file" do
11
- #Dir.glob("#{RAILS_ROOT}/db/migrate/*.rb").should_not be_empty
12
- #end
13
- #end