datts_right 0.0.31 → 0.0.32

Sign up to get free protection for your applications and to get access to all the features.
@@ -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