datts_right 0.0.31 → 0.0.32

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.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- datts_right (0.0.31)
4
+ datts_right (0.0.32)
5
5
  datts_right
6
6
 
7
7
  GEM
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.31
1
+ 0.0.32
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{datts_right}
8
- s.version = "0.0.31"
8
+ s.version = "0.0.32"
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"]
12
- s.date = %q{2011-04-27}
12
+ s.date = %q{2011-04-29}
13
13
  s.description = %q{Creates a separate table that saves all your dynamic attributes.}
14
14
  s.email = %q{ramon@tayag.net}
15
15
  s.extra_rdoc_files = [
@@ -31,12 +31,14 @@ Gem::Specification.new do |s|
31
31
  "lib/datts_right.rb",
32
32
  "lib/datts_right/base.rb",
33
33
  "lib/datts_right/category.rb",
34
+ "lib/datts_right/category_without_reflection.rb",
34
35
  "lib/datts_right/dynamic_attribute.rb",
35
36
  "lib/datts_right/dynamic_attribute_definition.rb",
36
37
  "lib/datts_right/errors.rb",
37
38
  "lib/datts_right/exceptions.rb",
38
39
  "lib/datts_right/instance_methods.rb",
39
40
  "lib/datts_right/page.rb",
41
+ "lib/datts_right/page_without_reflection.rb",
40
42
  "lib/datts_right/query_methods.rb",
41
43
  "spec/datt_spec.rb",
42
44
  "spec/datts_right/add_definition_spec.rb",
@@ -55,6 +57,7 @@ Gem::Specification.new do |s|
55
57
  "spec/datts_right/remove_definition_spec.rb",
56
58
  "spec/datts_right/remove_definitions_spec.rb",
57
59
  "spec/datts_right/remove_dynamic_attribute_spec.rb",
60
+ "spec/datts_right/sync_definition_spec.rb",
58
61
  "spec/datts_right/update_definition_spec.rb",
59
62
  "spec/datts_right/update_definitions_spec.rb",
60
63
  "spec/datts_right/where_dynamic_attribute_spec.rb",
@@ -87,6 +90,7 @@ Gem::Specification.new do |s|
87
90
  "spec/datts_right/remove_definition_spec.rb",
88
91
  "spec/datts_right/remove_definitions_spec.rb",
89
92
  "spec/datts_right/remove_dynamic_attribute_spec.rb",
93
+ "spec/datts_right/sync_definition_spec.rb",
90
94
  "spec/datts_right/update_definition_spec.rb",
91
95
  "spec/datts_right/update_definitions_spec.rb",
92
96
  "spec/datts_right/where_dynamic_attribute_spec.rb",
@@ -8,7 +8,7 @@ module DattsRight
8
8
  has_many :dynamic_attributes, :as => :attributable, :dependent => :destroy
9
9
  has_one :dynamic_attribute_definition, :as => :attribute_defineable, :dependent => :destroy
10
10
  after_save :save_dynamic_attribute_definition
11
- after_create :create_dynamic_attribute_definition_if_needed, :inherit_definition
11
+ after_create :create_dynamic_attribute_definition_if_needed, :inherit_definition!
12
12
  delegate :definition, :definition=, :to => :dynamic_attribute_definition
13
13
 
14
14
  # Carry out delayed actions before save
@@ -17,6 +17,7 @@ module DattsRight
17
17
  after_find :cache_dynamic_attributes
18
18
  default_scope includes(:dynamic_attributes).includes(:dynamic_attribute_definition)
19
19
 
20
+ #validate :must_be_reflected_by_definer
20
21
 
21
22
  # scope :scope_self when looking through attributes so we don't look through all dynamic_attributes
22
23
  # Why? What if you have Friend and Page models.
@@ -74,6 +75,38 @@ module DattsRight
74
75
  end
75
76
  end
76
77
 
78
+ def self.defines?(klass=nil)
79
+ return false unless !dynamic_attributes_options[:defines].nil? && !dynamic_attributes_options[:defines].empty?
80
+ #puts "There is [:defines], and it's not empty"
81
+ if klass
82
+ klass = klass.class unless klass.is_a?(Class)
83
+ klass_symbol = klass.name.downcase.to_sym
84
+ dynamic_attributes_options[:defines].include?(klass_symbol)
85
+ else
86
+ true
87
+ end
88
+ end
89
+
90
+ def self.defines
91
+ dynamic_attributes_options[:defines] if defines?
92
+ end
93
+
94
+ def self.defined?
95
+ dynamic_attributes_options[:of]
96
+ end
97
+
98
+ def self.defined_by?(arg)
99
+ return false unless self.defined?
100
+ symbol = if arg.is_a?(Class)
101
+ arg.name.underscore.to_sym
102
+ elsif arg.is_a?(Symbol)
103
+ arg
104
+ else # should be an instance
105
+ arg.class.name.underscore.to_sym
106
+ end
107
+ dynamic_attributes_options[:of] == symbol
108
+ end
109
+
77
110
  private
78
111
 
79
112
  def self.method_missing(method_id, *arguments)
@@ -1,5 +1,5 @@
1
1
  class Category < ActiveRecord::Base
2
- has_dynamic_attributes :definition => true
2
+ has_dynamic_attributes :defines => [:page]
3
3
  has_many :pages
4
4
 
5
5
  def definition_attributes=(new_attributes)
@@ -0,0 +1,4 @@
1
+ class CategoryWithoutReflection < ActiveRecord::Base
2
+ set_table_name "categories"
3
+ has_dynamic_attributes :defines => [:something_else]
4
+ end
@@ -117,7 +117,7 @@ module DattsRight
117
117
  end
118
118
 
119
119
  def create_dynamic_attribute_definition_if_needed
120
- if dynamic_attributes_options[:definition]
120
+ if self.defines?
121
121
  DynamicAttributeDefinition.create :attribute_defineable_id => self.id, :attribute_defineable_type => self.class.name, :definition => {}
122
122
  end
123
123
  end
@@ -126,7 +126,9 @@ module DattsRight
126
126
  if key
127
127
  key = key.to_sym
128
128
  #puts "add_definition(:#{key}, #{value.inspect}). current definition: #{definition.nil?}"
129
- if dynamic_attributes_options[:definition]
129
+ if dynamic_attributes_options[:defines].nil? || dynamic_attributes_options[:defines].empty?
130
+ raise NoDefinitionError
131
+ else
130
132
  #puts ":definition is true, so let's see if definition[:#{key}] already exists"
131
133
  # Checking definition straight seems to cause a problem. Is this a bug with Rails?
132
134
  # The problem was like this (assuming definition was actually nil):
@@ -142,8 +144,6 @@ module DattsRight
142
144
  else
143
145
  definition.merge!({key => value})
144
146
  end
145
- else
146
- raise NoDefinitionError
147
147
  end
148
148
  else
149
149
  raise AttributeKeyRequired
@@ -180,25 +180,20 @@ module DattsRight
180
180
  end
181
181
 
182
182
  def update_definition(key, new_values={})
183
- if dynamic_attributes_options[:definition]
184
- if definition && definition[key]
185
- attr_key = new_values.symbolize_keys[:attr_key]
186
- new_values.each do |k, v|
187
- definition[key][k] = v unless k.to_s == "attr_key"
188
- end
183
+ raise NoDefinitionError unless self.defines?
184
+ raise NotDefinedError, "#{key} is not defined" unless definition && definition[key]
189
185
 
190
- #puts "attr_key is #{attr_key}, key is #{key}"
191
- if attr_key && attr_key != key.to_s
192
- #puts "Adding definition: #{attr_key} => #{definition[key]}"
193
- add_definition(attr_key, definition[key])
194
- #puts "Removing definition: #{key} => #{definition[key]}"
195
- remove_definition(key)
196
- end
197
- else
198
- raise NotDefinedError, "#{key} is not defined"
199
- end
200
- else
201
- raise NoDefinitionError
186
+ attr_key = new_values.symbolize_keys[:attr_key]
187
+ new_values.each do |k, v|
188
+ definition[key][k] = v unless k.to_s == "attr_key"
189
+ end
190
+
191
+ #puts "attr_key is #{attr_key}, key is #{key}"
192
+ if attr_key && attr_key != key.to_s
193
+ #puts "Adding definition: #{attr_key} => #{definition[key]}"
194
+ add_definition(attr_key, definition[key])
195
+ #puts "Removing definition: #{key} => #{definition[key]}"
196
+ remove_definition(key)
202
197
  end
203
198
  end
204
199
 
@@ -211,15 +206,9 @@ module DattsRight
211
206
  def remove_definition(key)
212
207
  if key
213
208
  key = key.to_sym
214
- if dynamic_attributes_options[:definition]
215
- if definition && definition[key]
216
- definition.delete(key)
217
- else
218
- raise NotDefinedError, "#{key} is not defined"
219
- end
220
- else
221
- raise NoDefinitionError
222
- end
209
+ raise NoDefinitionError unless self.defines?
210
+ raise NotDefinedError, "#{key} is not defined" unless definition && definition[key]
211
+ definition.delete(key)
223
212
  end
224
213
  end
225
214
 
@@ -231,6 +220,71 @@ module DattsRight
231
220
  end
232
221
  end
233
222
 
223
+ # Adds dynamic attributes to inheriting model, based on the definition of the defining model.
224
+ # class InheritingModel < AR::Base
225
+ # has_dynamic_attributes :of => :defining_model
226
+ # end
227
+ #
228
+ # The DefiningModel should have the code:
229
+ # class DefiningModel < AR::Base
230
+ # has_dynamic_attributes :defines => [:inheriting_model]
231
+ # end
232
+ #
233
+ # Example:
234
+ # @defining_model.add_definitions(:name => {:object_type => "string"}, :body => {:object_type => "text"})
235
+ # @defining_model.save
236
+ # InheritingModel.create # creates an instance with dynamic attributes: name and body, that are "string" and "text", respectively
237
+ #
238
+ # Calling this method manually only _adds_ to the inheriting instance you call it on. If you remove some definitions from the defining model, then you call @inheriting_model.inherit_definition!@, the new definitions will be added. If there are no new definitions, nothing will happen.
239
+ def inherit_definition!
240
+ #puts "In inherit_definition"
241
+ #puts "------- #{dynamic_attributes_options[:of]}"
242
+ #dynamic_attribute_definition.create if dynamic_attributes_options[:definition]
243
+ if self.defined? && defining_record
244
+ defining_record.definition.each do |k, v|
245
+ datt = add_dynamic_attribute(k, v[:object_type])
246
+ datt.dynamic_attribute_definition
247
+ #puts "Added #{datt.inspect}"
248
+ end
249
+ end
250
+ end
251
+
252
+ # Adds and removes dynamic attributes based on the defining record
253
+ def sync_definition!
254
+ defining_record.definition.each do |k, v|
255
+ add_dynamic_attribute(k, v[:object_type]) if dynamic_attribute_details(k).nil?
256
+ end
257
+ @dynamic_attributes_cache.each do |k, v|
258
+ #puts "Remove #{k}?"
259
+ remove_dynamic_attribute(k) if v.definer.nil?
260
+ end
261
+ end
262
+
263
+ # Returns true if this defines any other class
264
+ def defines?(klass=nil)
265
+ self.class.defines?(klass)
266
+ end
267
+
268
+ # Returns true if this is defined by any other class
269
+ def defined?
270
+ self.class.defined?
271
+ end
272
+
273
+ # Returns true if the calling instance is defined by the argument
274
+ def defined_by?(arg)
275
+ self.class.defined_by?(arg)
276
+ end
277
+
278
+ # Returns an array of symbols of the classes that this defines
279
+ def defines
280
+ self.class.defines
281
+ end
282
+
283
+ #def must_be_reflected_by_definer
284
+ #errors.add(:base, "#{self.class.name} inherits its definition from #{dynamic_attributes_options[:of]} but that does not define #{self.class.name}.") \
285
+ #unless dynamic_attributes_options[:of].to_s.classify.constantize.defines?(self.class)
286
+ #end
287
+
234
288
  private
235
289
 
236
290
  # Called after validation on update so that dynamic attributes behave
@@ -267,22 +321,6 @@ module DattsRight
267
321
  dynamic_attribute_definition.save if dynamic_attribute_definition
268
322
  end
269
323
 
270
- def inherit_definition
271
- #puts "In inherit_definition"
272
- #puts "------- #{dynamic_attributes_options[:of]}"
273
- #dynamic_attribute_definition.create if dynamic_attributes_options[:definition]
274
- if dynamic_attributes_options[:of]
275
- #puts "There is a defining record of #{self.class.name}##{self.name} in #{defining_record.inspect}. #{defining_record.dynamic_attribute_definition.inspect}"
276
- if defining_record
277
- defining_record.definition.each do |k, v|
278
- datt = add_dynamic_attribute(k, v[:object_type])
279
- datt.dynamic_attribute_definition
280
- #puts "Added #{datt.inspect}"
281
- end
282
- end
283
- end
284
- end
285
-
286
324
  alias :add_datt :add_dynamic_attribute
287
325
  alias :add_datt! :add_dynamic_attribute!
288
326
  alias :remove_datt :remove_dynamic_attribute
@@ -0,0 +1,9 @@
1
+ class PageWithoutReflection < ActiveRecord::Base
2
+ set_table_name "pages"
3
+ belongs_to :category_without_reflection
4
+ has_dynamic_attributes :of => :category_without_reflection
5
+
6
+ def virtual_attribute=(something)
7
+ puts "Setting virtual_attribute to #{something}"
8
+ end
9
+ end
@@ -4,4 +4,50 @@ describe DattsRight, "on the definition" do
4
4
  it "should not be created if it is not defined" do
5
5
  Page.create.dynamic_attribute_definition.should be_nil
6
6
  end
7
+
8
+ describe ".defines?" do
9
+ it "should return true if nil is passed, and it has the option and it's not empty" do
10
+ Category.defines?.should be_true
11
+ Category.new.defines?.should be_true
12
+ end
13
+
14
+ it "should return true if a class is passed, it has the option, and it defines the class" do
15
+ Category.defines?(Page).should be_true
16
+ Category.new.defines?(Page).should be_true
17
+ Category.defines?(Page.new).should be_true
18
+ Category.new.defines?(Page.new).should be_true
19
+ end
20
+ end
21
+
22
+ describe ".defines" do
23
+ it "should return the array of classes that it defines" do
24
+ Category.defines.should == [:page]
25
+ Category.new.defines.should == [:page]
26
+ end
27
+
28
+ it "should return nil if it does not define anything" do
29
+ Page.defines.should be_nil
30
+ Page.new.defines.should be_nil
31
+ end
32
+ end
33
+
34
+ describe ".defined?" do
35
+ it "should return true if it has the option and it's not empty" do
36
+ Page.defined?.should be_true
37
+ Page.new.defined?.should be_true
38
+ end
39
+ end
40
+
41
+ describe ".defined_by?(klass_or_instance)" do
42
+ it "should return true if a class is passed, it has the option, and it defines the class" do
43
+ Page.defined_by?(Category).should be_true
44
+ Page.defined_by?(Category.new).should be_true
45
+ Page.defined_by?(:category).should be_true
46
+ end
47
+
48
+ it "should be the same as the instance method" do
49
+ Page.should_receive(:defined_by?).with(Category)
50
+ Page.new.defined_by?(Category)
51
+ end
52
+ end
7
53
  end
@@ -0,0 +1,26 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe DattsRight, ".sync_definition!" do
4
+ before do
5
+ reset_database
6
+ @category = Category.create
7
+ @category.definition = {:teaser => {:object_type => "text"}, :body => {:object_type => "text"}}
8
+ @category.save
9
+ @page = Page.create :category => @category
10
+ end
11
+
12
+ it "should add any new definitions" do
13
+ @category.add_definition(:price, {:object_type => "integer"})
14
+ @category.save
15
+ @page.sync_definition!
16
+ @page.dynamic_attribute_details(:price)[:object_type].should == "integer"
17
+ end
18
+
19
+ it "should remove any dynamic attributes if the definitions are removed" do
20
+ @category.remove_definition(:body)
21
+ @category.save
22
+ @page.sync_definition!
23
+ @page.dynamic_attribute_details(:teaser)[:object_type].should == "text"
24
+ lambda {@page.body}.should raise_error(NoMethodError)
25
+ end
26
+ end
@@ -178,4 +178,8 @@ describe DattsRight do
178
178
  it "should still allow virtual attributes to work (for mass assignment)" do
179
179
  lambda {Category.create.update_attributes(:definition_attributes => {"attr_key" => "some_attr", "object_type" => "string"}, :name => "hello")}.should_not raise_error(ActiveRecord::UnknownAttributeError)
180
180
  end
181
+
182
+ #it "should validate reflection of inheritance" do
183
+ #PageWithoutReflection.new.errors[:base].should include("Page inherits its definition from category_without_reflection but that does not define Page.")
184
+ #end
181
185
  end
@@ -6,7 +6,9 @@ require 'active_record/errors'
6
6
  require 'rspec'
7
7
  require 'datts_right'
8
8
  require 'datts_right/page'
9
+ require 'datts_right/page_without_reflection'
9
10
  require 'datts_right/category'
11
+ require 'datts_right/category_without_reflection'
10
12
 
11
13
  # Allow to connect to SQLite
12
14
  root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
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: 33
4
+ hash: 95
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 31
10
- version: 0.0.31
9
+ - 32
10
+ version: 0.0.32
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ramon Tayag
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-27 00:00:00 +08:00
18
+ date: 2011-04-29 00:00:00 +08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -162,12 +162,14 @@ files:
162
162
  - lib/datts_right.rb
163
163
  - lib/datts_right/base.rb
164
164
  - lib/datts_right/category.rb
165
+ - lib/datts_right/category_without_reflection.rb
165
166
  - lib/datts_right/dynamic_attribute.rb
166
167
  - lib/datts_right/dynamic_attribute_definition.rb
167
168
  - lib/datts_right/errors.rb
168
169
  - lib/datts_right/exceptions.rb
169
170
  - lib/datts_right/instance_methods.rb
170
171
  - lib/datts_right/page.rb
172
+ - lib/datts_right/page_without_reflection.rb
171
173
  - lib/datts_right/query_methods.rb
172
174
  - spec/datt_spec.rb
173
175
  - spec/datts_right/add_definition_spec.rb
@@ -186,6 +188,7 @@ files:
186
188
  - spec/datts_right/remove_definition_spec.rb
187
189
  - spec/datts_right/remove_definitions_spec.rb
188
190
  - spec/datts_right/remove_dynamic_attribute_spec.rb
191
+ - spec/datts_right/sync_definition_spec.rb
189
192
  - spec/datts_right/update_definition_spec.rb
190
193
  - spec/datts_right/update_definitions_spec.rb
191
194
  - spec/datts_right/where_dynamic_attribute_spec.rb
@@ -246,6 +249,7 @@ test_files:
246
249
  - spec/datts_right/remove_definition_spec.rb
247
250
  - spec/datts_right/remove_definitions_spec.rb
248
251
  - spec/datts_right/remove_dynamic_attribute_spec.rb
252
+ - spec/datts_right/sync_definition_spec.rb
249
253
  - spec/datts_right/update_definition_spec.rb
250
254
  - spec/datts_right/update_definitions_spec.rb
251
255
  - spec/datts_right/where_dynamic_attribute_spec.rb