tableless_model 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc
CHANGED
@@ -27,7 +27,8 @@ module Base
|
|
27
27
|
|
28
28
|
# if only the column name is given, the tableless model's class is expected to have that name, classified, as class name
|
29
29
|
class_type = column.class == Hash ? column.collect{|k,v| v}.last : column.to_s.classify.constantize
|
30
|
-
|
30
|
+
|
31
|
+
|
31
32
|
# injecting in the parent object a getter and a setter for the
|
32
33
|
# attribute that will store an instance of a tableless model
|
33
34
|
class_eval do
|
@@ -41,7 +42,12 @@ module Base
|
|
41
42
|
# model and not just a normal hash or the value of the attribute in the database,
|
42
43
|
# which is plain text
|
43
44
|
define_method column_name.to_s do
|
44
|
-
class_type.new(read_attribute(column_name.to_sym) || {})
|
45
|
+
instance = class_type.new(read_attribute(column_name.to_sym) || {})
|
46
|
+
|
47
|
+
instance.__owner_object = self
|
48
|
+
instance.__serialized_attribute = column_name
|
49
|
+
|
50
|
+
instance
|
45
51
|
end
|
46
52
|
|
47
53
|
# Adding setter for the serialized column,
|
data/lib/tableless_model.rb
CHANGED
@@ -12,8 +12,12 @@ module ActiveRecord
|
|
12
12
|
class TablelessModel < Hash
|
13
13
|
|
14
14
|
extend Tableless::ClassMethods
|
15
|
+
|
15
16
|
include Tableless::InstanceMethods
|
16
|
-
include
|
17
|
+
include Validatable
|
18
|
+
|
19
|
+
|
20
|
+
attr_accessor :__owner_object, :__serialized_attribute
|
17
21
|
|
18
22
|
#
|
19
23
|
#
|
@@ -24,6 +28,7 @@ module ActiveRecord
|
|
24
28
|
#
|
25
29
|
class << self
|
26
30
|
attr_reader :attributes
|
31
|
+
|
27
32
|
end
|
28
33
|
|
29
34
|
end
|
@@ -46,7 +46,17 @@ module Tableless
|
|
46
46
|
#
|
47
47
|
def []=(attribute_name, value)
|
48
48
|
raise NoMethodError, "The attribute #{attribute_name} is undefined" unless self.class.attributes.has_key? attribute_name.to_s
|
49
|
-
|
49
|
+
|
50
|
+
return_value = super(attribute_name.to_s, self.class.cast(attribute_name, value))
|
51
|
+
|
52
|
+
if self.__owner_object
|
53
|
+
# This makes the tableless model compatible with partial_updates:
|
54
|
+
# whenever a property in the tableless model is changed, we force the parent/owner object to a changed state
|
55
|
+
# by updating it with a new, updated instance of the tableless model
|
56
|
+
self.__owner_object.send "#{self.__serialized_attribute.to_s}=".to_sym, self
|
57
|
+
end
|
58
|
+
|
59
|
+
return_value
|
50
60
|
end
|
51
61
|
|
52
62
|
|
@@ -98,6 +98,22 @@ describe "An instance of TablelessModel" do
|
|
98
98
|
attribute :typed_test_attribute, :type => :integer
|
99
99
|
end
|
100
100
|
end
|
101
|
+
|
102
|
+
describe "instance" do
|
103
|
+
before do
|
104
|
+
@instance = TestClass3.new
|
105
|
+
end
|
106
|
+
|
107
|
+
it "has rw the accessor __owner_object" do
|
108
|
+
@instance.must_respond_to "__owner_object"
|
109
|
+
@instance.must_respond_to "__owner_object="
|
110
|
+
end
|
111
|
+
|
112
|
+
it "has rw the accessor __serialized_attribute" do
|
113
|
+
@instance.must_respond_to "__serialized_attribute"
|
114
|
+
@instance.must_respond_to "__serialized_attribute="
|
115
|
+
end
|
116
|
+
end
|
101
117
|
|
102
118
|
it "tries to enforce type casting if a type has been specified for an attribute" do
|
103
119
|
|
@@ -140,14 +156,13 @@ describe "An instance of TablelessModel" do
|
|
140
156
|
end
|
141
157
|
end
|
142
158
|
|
143
|
-
|
144
159
|
describe "An ActiveRecord::Base model" do
|
145
160
|
before do
|
146
161
|
class ModelOptions < ActiveRecord::TablelessModel
|
147
162
|
attribute :aaa, :default => 111
|
148
163
|
attribute :bbb, :default => "bbb"
|
149
164
|
end
|
150
|
-
|
165
|
+
|
151
166
|
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
152
167
|
ActiveRecord::Base.connection.execute(" create table test_models (options varchar(50)) ")
|
153
168
|
|
@@ -155,16 +170,32 @@ describe "An ActiveRecord::Base model" do
|
|
155
170
|
has_tableless :options => ModelOptions
|
156
171
|
end
|
157
172
|
end
|
158
|
-
|
173
|
+
|
159
174
|
it "responds to default_value_for, has_tableless" do
|
160
175
|
TestModel.must_respond_to(:has_tableless)
|
161
176
|
end
|
162
177
|
|
163
|
-
|
178
|
+
|
179
|
+
describe "instance" do
|
164
180
|
before do
|
165
181
|
@instance = TestModel.new
|
166
182
|
end
|
167
183
|
|
184
|
+
it "must respond to changed?" do
|
185
|
+
@instance.must_respond_to "changed?"
|
186
|
+
@instance.changed?.must_equal false
|
187
|
+
@instance.changes.must_equal({})
|
188
|
+
end
|
189
|
+
|
190
|
+
it "sets the accessor __owner_object to self in the tableless model instance" do
|
191
|
+
@instance.options.__owner_object.must_equal @instance
|
192
|
+
end
|
193
|
+
|
194
|
+
it "sets the accessor __serialized_attribute to the name of its column that stored the tableless model instance, serialized" do
|
195
|
+
@instance.options.__serialized_attribute.must_equal :options
|
196
|
+
end
|
197
|
+
|
198
|
+
|
168
199
|
it "has a getter and a setter for :options" do
|
169
200
|
%w(options options=).each{|m| @instance.must_respond_to m }
|
170
201
|
@instance.options.must_be_kind_of ModelOptions
|
@@ -173,12 +204,12 @@ describe "An ActiveRecord::Base model" do
|
|
173
204
|
@instance.options.bbb.must_equal "bbb"
|
174
205
|
proc { @instance.options = "test" }.must_raise NoMethodError, "should not accept other values than a hash or ModelOptions instance"
|
175
206
|
end
|
176
|
-
|
207
|
+
|
177
208
|
describe "setter" do
|
178
209
|
before do
|
179
210
|
@return_value = @instance.send("options=", { :aaa => "CCC", :bbb => "DDD" })
|
180
211
|
end
|
181
|
-
|
212
|
+
|
182
213
|
it "correctly sets the serialized column" do
|
183
214
|
@return_value.must_be_kind_of ModelOptions
|
184
215
|
%w(aaa bbb).each{|m| @return_value.must_respond_to m}
|
@@ -186,18 +217,30 @@ describe "An ActiveRecord::Base model" do
|
|
186
217
|
@instance.options.bbb.must_equal "DDD"
|
187
218
|
end
|
188
219
|
|
220
|
+
it "forces the owner object to a changed state with partial_updates on" do
|
221
|
+
@instance.options.aaa = "changed aaa"
|
222
|
+
@instance.options.bbb = "changed bbb"
|
223
|
+
|
224
|
+
@instance.options.aaa.must_equal "changed aaa"
|
225
|
+
@instance.changes.keys.include?("options").must_equal true
|
226
|
+
|
227
|
+
@instance.changes[:options][0].must_equal nil
|
228
|
+
@instance.changes[:options][1].must_equal({"aaa"=>"changed aaa", "bbb"=>"changed bbb"})
|
229
|
+
end
|
230
|
+
|
189
231
|
it "should save the serialized column correctly" do
|
190
232
|
@instance.save!
|
191
|
-
|
192
|
-
|
193
|
-
@instance.options.aaa.must_equal "CCC"
|
194
|
-
@instance.options.bbb.must_equal "DDD"
|
233
|
+
|
234
|
+
instance = TestModel.first
|
195
235
|
|
196
|
-
|
197
|
-
|
236
|
+
instance.options.aaa.must_equal "CCC"
|
237
|
+
instance.options.bbb.must_equal "DDD"
|
198
238
|
|
239
|
+
# Ensuring the serialize macro is used
|
240
|
+
instance.options.must_be_kind_of ModelOptions
|
199
241
|
end
|
200
242
|
end
|
201
243
|
end
|
244
|
+
end
|
245
|
+
|
202
246
|
|
203
|
-
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 6
|
9
|
+
version: 0.0.6
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Vito Botta
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-01-
|
17
|
+
date: 2011-01-12 00:00:00 +00:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|