tenacity 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/EXTEND.rdoc +32 -22
- data/LICENSE.txt +1 -1
- data/README.rdoc +14 -16
- data/Rakefile +0 -37
- data/history.txt +21 -0
- data/lib/tenacity.rb +2 -1
- data/lib/tenacity/association.rb +82 -0
- data/lib/tenacity/associations/belongs_to.rb +9 -9
- data/lib/tenacity/associations/has_many.rb +19 -31
- data/lib/tenacity/associations/has_one.rb +7 -23
- data/lib/tenacity/class_methods.rb +136 -33
- data/lib/tenacity/instance_methods.rb +9 -13
- data/lib/tenacity/orm_ext/activerecord.rb +13 -30
- data/lib/tenacity/orm_ext/couchrest/couchrest_extended_document.rb +1 -4
- data/lib/tenacity/orm_ext/couchrest/couchrest_model.rb +1 -4
- data/lib/tenacity/orm_ext/couchrest/tenacity_class_methods.rb +8 -17
- data/lib/tenacity/orm_ext/couchrest/tenacity_instance_methods.rb +6 -6
- data/lib/tenacity/orm_ext/mongo_mapper.rb +15 -25
- data/lib/tenacity/version.rb +1 -1
- data/tenacity.gemspec +3 -3
- data/test/associations/belongs_to_test.rb +17 -1
- data/test/associations/has_many_test.rb +22 -0
- data/test/associations/has_one_test.rb +15 -0
- data/test/fixtures/active_record_car.rb +4 -0
- data/test/fixtures/active_record_engine.rb +5 -0
- data/test/fixtures/couch_rest_door.rb +10 -0
- data/test/fixtures/couch_rest_windshield.rb +10 -0
- data/test/fixtures/mongo_mapper_ash_tray.rb +8 -0
- data/test/fixtures/mongo_mapper_dashboard.rb +3 -0
- data/test/fixtures/mongo_mapper_vent.rb +8 -0
- data/test/fixtures/mongo_mapper_wheel.rb +1 -1
- data/test/helpers/active_record_test_helper.rb +34 -4
- data/test/orm_ext/activerecord_test.rb +15 -8
- data/test/orm_ext/couchrest_test.rb +15 -8
- data/test/orm_ext/mongo_mapper_test.rb +14 -8
- data/test/test_helper.rb +5 -2
- metadata +16 -11
- data/Gemfile.lock +0 -70
@@ -3,35 +3,19 @@ module Tenacity
|
|
3
3
|
|
4
4
|
private
|
5
5
|
|
6
|
-
def has_one_associate(
|
7
|
-
clazz = associate_class
|
8
|
-
clazz._t_find_first_by_associate(
|
6
|
+
def has_one_associate(association)
|
7
|
+
clazz = association.associate_class
|
8
|
+
clazz._t_find_first_by_associate(association.foreign_key(self.class), self.id.to_s)
|
9
9
|
end
|
10
10
|
|
11
|
-
def set_has_one_associate(
|
12
|
-
associate.send "#{
|
11
|
+
def set_has_one_associate(association, associate)
|
12
|
+
associate.send "#{association.foreign_key(self.class)}=", self.id.to_s
|
13
13
|
associate.save
|
14
14
|
end
|
15
15
|
|
16
|
-
def property_name
|
17
|
-
"#{ActiveSupport::Inflector.underscore(self.class.to_s)}_id"
|
18
|
-
end
|
19
|
-
|
20
16
|
module ClassMethods #:nodoc:
|
21
|
-
def initialize_has_one_association(
|
22
|
-
|
23
|
-
require association_id.to_s
|
24
|
-
rescue Exception => e
|
25
|
-
puts "ERROR: #{association_id.to_s} does not appear to be in the load path. Please make sure all model files are in the load path."
|
26
|
-
raise
|
27
|
-
end
|
28
|
-
|
29
|
-
clazz = associate_class(association_id)
|
30
|
-
clazz._t_initialize_has_one_association(ActiveSupport::Inflector.underscore(self.to_s)) if clazz.respond_to?(:_t_initialize_has_one_association)
|
31
|
-
end
|
32
|
-
|
33
|
-
def _t_stringify_has_one_value(record, association_id)
|
34
|
-
record.send "#{association_id}_id=", record.send("#{association_id}_id").to_s
|
17
|
+
def initialize_has_one_association(association)
|
18
|
+
_t_initialize_has_one_association(association) if respond_to?(:_t_initialize_has_one_association)
|
35
19
|
end
|
36
20
|
end
|
37
21
|
|
@@ -70,6 +70,32 @@ module Tenacity
|
|
70
70
|
# project.milestones(true).size # fetches milestones from the database
|
71
71
|
# project.milestones # uses the milestone cache
|
72
72
|
#
|
73
|
+
# == Join Tables
|
74
|
+
#
|
75
|
+
# One-to-many assocations that contain a relational database backed object as one of
|
76
|
+
# the assocaites are implemented using an intermediate join table. This differs from
|
77
|
+
# ActiveRecord::Associations, where only many-to-many relationships are implemented
|
78
|
+
# using an intermediate join table.
|
79
|
+
#
|
80
|
+
# Tenacity will not create the join table. It assume one exists, and is named properly.
|
81
|
+
# Unless the join table is explicitly specified as an option, it is guessed using the
|
82
|
+
# lexical order of the class names. So a join between Developer and Project will give
|
83
|
+
# the default join table name of "developers_projects" because "D" outranks "P". Note
|
84
|
+
# that this precedence is calculated using the < operator for String. This means that
|
85
|
+
# if the strings are of different lengths, and the strings are equal when compared up
|
86
|
+
# to the shortest length, then the longer string is considered of higher lexical
|
87
|
+
# precedence than the shorter one. For example, one would expect the tables "paper_boxes"
|
88
|
+
# and "papers" to generate a join table name of "papers_paper_boxes" because of the
|
89
|
+
# length of the name "paper_boxes", but it in fact generates a join table name of
|
90
|
+
# "paper_boxes_papers". Be aware of this caveat, and use the custom :join_table option
|
91
|
+
# if you need to.
|
92
|
+
#
|
93
|
+
# The column names used in the join table are guessed to be the names of the associated
|
94
|
+
# classes, suffixed with "_id". For example, the "developers_projects" join table
|
95
|
+
# mentioned above is expected to have a column named "developer_id" and a column named
|
96
|
+
# "project_id". The <tt>:associate_key</tt> and <tt>:associate_foreign_key</tt> options
|
97
|
+
# can be used to override these defaults.
|
98
|
+
#
|
73
99
|
module ClassMethods
|
74
100
|
|
75
101
|
# Specifies a one-to-one association with another class. This method should only be used
|
@@ -93,19 +119,34 @@ module Tenacity
|
|
93
119
|
# * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.find(:first, :conditions => "account_id = #{id}")</tt>)
|
94
120
|
# * <tt>Account#beneficiary=(beneficiary)</tt> (similar to <tt>beneficiary.account_id = account.id; beneficiary.save</tt>)
|
95
121
|
#
|
96
|
-
|
122
|
+
# === Supported options
|
123
|
+
# [:class_name]
|
124
|
+
# Specify the class name of the association. Use it only if that name can't be inferred
|
125
|
+
# from the association name. So <tt>t_has_one :manager</tt> will by default be linked to the Manager class, but
|
126
|
+
# if the real class name is Person, you'll have to specify it with this option.
|
127
|
+
# [:foreign_key]
|
128
|
+
# Specify the foreign key used for the association. By default this is guessed to be the name
|
129
|
+
# of this class in lower-case and "_id" suffixed. So a Person class that makes a +t_has_one+ association
|
130
|
+
# will use "person_id" as the default <tt>:foreign_key</tt>.
|
131
|
+
#
|
132
|
+
# Option examples:
|
133
|
+
# t_has_one :project_manager, :class_name => "Person"
|
134
|
+
# t_has_one :project_manager, :foreign_key => "project_id" # within class named SecretProject
|
135
|
+
#
|
136
|
+
def t_has_one(name, options={})
|
97
137
|
extend(HasOne::ClassMethods)
|
98
|
-
|
138
|
+
association = Association.new(:t_has_one, name, self, options)
|
139
|
+
initialize_has_one_association(association)
|
99
140
|
|
100
|
-
define_method(
|
101
|
-
get_associate(
|
102
|
-
has_one_associate(
|
141
|
+
define_method(association.name) do |*params|
|
142
|
+
get_associate(association, params) do
|
143
|
+
has_one_associate(association)
|
103
144
|
end
|
104
145
|
end
|
105
146
|
|
106
|
-
define_method("#{
|
107
|
-
set_associate(
|
108
|
-
set_has_one_associate(
|
147
|
+
define_method("#{association.name}=") do |associate|
|
148
|
+
set_associate(association, associate) do
|
149
|
+
set_has_one_associate(association, associate)
|
109
150
|
end
|
110
151
|
end
|
111
152
|
end
|
@@ -131,25 +172,46 @@ module Tenacity
|
|
131
172
|
# * <tt>Post#author</tt> (similar to <tt>Author.find(author_id)</tt>)
|
132
173
|
# * <tt>Post#author=(author)</tt> (similar to <tt>post.author_id = author.id</tt>)
|
133
174
|
#
|
134
|
-
|
175
|
+
# === Supported options
|
176
|
+
# [:class_name]
|
177
|
+
# Specify the class name of the association. Use it only if that name can't be inferred
|
178
|
+
# from the association name. So <tt>t_belongs_to :manager</tt> will by default be linked to the Manager class, but
|
179
|
+
# if the real class name is Person, you'll have to specify it with this option.
|
180
|
+
# [:foreign_key]
|
181
|
+
# Specify the foreign key used for the association. By default this is guessed to be the name
|
182
|
+
# of the association with an "_id" suffix. So a class that defines a <tt>t_belongs_to :person</tt>
|
183
|
+
# association will use "person_id" as the default <tt>:foreign_key</tt>. Similarly,
|
184
|
+
# <tt>t_belongs_to :favorite_person, :class_name => "Person"</tt> will use a foreign key
|
185
|
+
# of "favorite_person_id".
|
186
|
+
#
|
187
|
+
# Option examples:
|
188
|
+
# t_belongs_to :project_manager, :class_name => "Person"
|
189
|
+
# t_belongs_to :valid_coupon, :class_name => "Coupon", :foreign_key => "coupon_id"
|
190
|
+
#
|
191
|
+
def t_belongs_to(name, options={})
|
135
192
|
extend(BelongsTo::ClassMethods)
|
136
|
-
|
193
|
+
association = Association.new(:t_belongs_to, name, self, options)
|
194
|
+
initialize_belongs_to_association(association)
|
137
195
|
|
138
|
-
define_method(
|
139
|
-
get_associate(
|
140
|
-
belongs_to_associate(
|
196
|
+
define_method(association.name) do |*params|
|
197
|
+
get_associate(association, params) do
|
198
|
+
belongs_to_associate(association)
|
141
199
|
end
|
142
200
|
end
|
143
201
|
|
144
|
-
define_method("#{
|
145
|
-
set_associate(
|
146
|
-
set_belongs_to_associate(
|
202
|
+
define_method("#{association.name}=") do |associate|
|
203
|
+
set_associate(association, associate) do
|
204
|
+
set_belongs_to_associate(association, associate)
|
147
205
|
end
|
148
206
|
end
|
149
207
|
end
|
150
208
|
|
151
|
-
# Specifies a one-to-many association.
|
152
|
-
#
|
209
|
+
# Specifies a one-to-many association. One-to-many associations that contain a
|
210
|
+
# relational database backed object as one of the associates are implemented
|
211
|
+
# using an intermediate join table. See the Join Tables section at the top
|
212
|
+
# for more information.
|
213
|
+
#
|
214
|
+
# The following methods for retrieval and query of collections of associated objects will be added:
|
153
215
|
#
|
154
216
|
# [collection(force_reload = false)]
|
155
217
|
# Returns an array of all the associated objects.
|
@@ -188,26 +250,71 @@ module Tenacity
|
|
188
250
|
# * <tt>Firm#clients.empty?</tt> (similar to <tt>firm.clients.size == 0</tt>)
|
189
251
|
# * <tt>Firm#clients.size</tt> (similar to <tt>Client.count "firm_id = #{id}"</tt>)
|
190
252
|
#
|
191
|
-
|
253
|
+
# === Supported options
|
254
|
+
# [:class_name]
|
255
|
+
# Specify the class name of the association. Use it only if that name can't be inferred
|
256
|
+
# from the association name. So <tt>t_has_many :products</tt> will by default be linked
|
257
|
+
# to the Product class, but if the real class name is SpecialProduct, you'll have to
|
258
|
+
# specify it with this option.
|
259
|
+
# [:foreign_key]
|
260
|
+
# Specify the foreign key used for the association. By default this is guessed to be the name
|
261
|
+
# of this class in lower-case and "_id" suffixed. So a Person class that makes a +t_has_many+
|
262
|
+
# association will use "person_id" as the default <tt>:foreign_key</tt>.
|
263
|
+
# [:foreign_keys_property]
|
264
|
+
# Specify the name of the property that stores the ids of the associated objects. By default
|
265
|
+
# this is guessed to be the name of the association with a "t_" prefix and an "_ids" suffix.
|
266
|
+
# So a class that defines a <tt>t_has_many :people</tt> association will use t_people_ids as
|
267
|
+
# the property to store the ids of the associated People objects. This option is only valid
|
268
|
+
# for objects that store associated ids in an array instaed of a join table (CouchRest,
|
269
|
+
# MongoMapper, etc). <b>WARNING:</b> The name of the association with an "_ids" suffix should
|
270
|
+
# not be used as the property name, since tenacity adds a method with this name to the object.
|
271
|
+
# [:join_table]
|
272
|
+
# Specify the name of the join table if the default based on lexical order isn't what you want.
|
273
|
+
# This option is only valid if one of the models in the association is backed by a relational
|
274
|
+
# database.
|
275
|
+
# [:association_foreign_key]
|
276
|
+
# Specify the foreign key in the join table used for the association on the receiving side of
|
277
|
+
# the association. By default this is guessed to be the name of the associated class in
|
278
|
+
# lower-case and "_id" suffixed. So if a Person class makes a +t_has_many+ association to
|
279
|
+
# Project, the association will use "project_id" as the default <tt>:association_foreign_key</tt>.
|
280
|
+
# This option is only valid if one of the associated objects is backed by a relational
|
281
|
+
# database.
|
282
|
+
# [:association_key]
|
283
|
+
# Specify the key in the join table used for the association on the declaring side of
|
284
|
+
# the association. By default this is guessed to be the name of this class in lower-case and
|
285
|
+
# "_id" suffixed. So if a Person class makes a +t_has_many+ association to Project, the
|
286
|
+
# association will use "person_id" as the default <tt>:association_key</tt>. This option is
|
287
|
+
# only valid if one of the associated objects is backed by a relational database.
|
288
|
+
#
|
289
|
+
# Option examples:
|
290
|
+
# t_has_many :products, :class_name => "SpecialProduct"
|
291
|
+
# t_has_many :engineers, :foreign_key => "project_id" # within class named SecretProject
|
292
|
+
# t_has_many :engineers, :foreign_keys_property => "worker_ids"
|
293
|
+
# t_has_many :managers, :join_table => "project_managers_and_projects"
|
294
|
+
# t_has_many :managers, :join_table => "project_managers_and_projects",
|
295
|
+
# :association_foreign_key => "mgr_id", :association_key => "proj_id"
|
296
|
+
#
|
297
|
+
def t_has_many(name, options={})
|
192
298
|
extend(HasMany::ClassMethods)
|
193
|
-
|
299
|
+
association = Association.new(:t_has_many, name, self, options)
|
300
|
+
initialize_has_many_association(association)
|
194
301
|
|
195
|
-
define_method(
|
196
|
-
get_associate(
|
197
|
-
has_many_associates(
|
302
|
+
define_method(association.name) do |*params|
|
303
|
+
get_associate(association, params) do
|
304
|
+
has_many_associates(association)
|
198
305
|
end
|
199
306
|
end
|
200
307
|
|
201
|
-
define_method("#{
|
202
|
-
set_associate(
|
308
|
+
define_method("#{association.name}=") do |associates|
|
309
|
+
set_associate(association, associates)
|
203
310
|
end
|
204
311
|
|
205
|
-
define_method("#{ActiveSupport::Inflector.singularize(
|
206
|
-
has_many_associate_ids(
|
312
|
+
define_method("#{ActiveSupport::Inflector.singularize(association.name)}_ids") do
|
313
|
+
has_many_associate_ids(association)
|
207
314
|
end
|
208
315
|
|
209
|
-
define_method("#{ActiveSupport::Inflector.singularize(
|
210
|
-
set_has_many_associate_ids(
|
316
|
+
define_method("#{ActiveSupport::Inflector.singularize(association.name)}_ids=") do |associate_ids|
|
317
|
+
set_has_many_associate_ids(association, associate_ids)
|
211
318
|
end
|
212
319
|
|
213
320
|
private
|
@@ -217,10 +324,6 @@ module Tenacity
|
|
217
324
|
end
|
218
325
|
end
|
219
326
|
|
220
|
-
def associate_class(association_id) #:nodoc:
|
221
|
-
Kernel.const_get(association_id.to_s.singularize.camelcase.to_sym)
|
222
|
-
end
|
223
|
-
|
224
327
|
end
|
225
328
|
end
|
226
329
|
|
@@ -1,30 +1,26 @@
|
|
1
1
|
module Tenacity
|
2
2
|
module InstanceMethods #:nodoc:
|
3
3
|
|
4
|
+
def _t_ivar_name(association)
|
5
|
+
"@_t_" + association.name.to_s
|
6
|
+
end
|
7
|
+
|
4
8
|
private
|
5
9
|
|
6
|
-
def get_associate(
|
10
|
+
def get_associate(association, params)
|
7
11
|
_t_reload
|
8
12
|
force_reload = params.first unless params.empty?
|
9
|
-
value = instance_variable_get
|
13
|
+
value = instance_variable_get _t_ivar_name(association)
|
10
14
|
if value.nil? || force_reload
|
11
15
|
value = yield
|
12
|
-
instance_variable_set
|
16
|
+
instance_variable_set _t_ivar_name(association), value
|
13
17
|
end
|
14
18
|
value
|
15
19
|
end
|
16
20
|
|
17
|
-
def set_associate(
|
21
|
+
def set_associate(association, associate)
|
18
22
|
yield if block_given?
|
19
|
-
instance_variable_set
|
20
|
-
end
|
21
|
-
|
22
|
-
def ivar_name(association_id)
|
23
|
-
"@_t_" + association_id.to_s
|
24
|
-
end
|
25
|
-
|
26
|
-
def associate_class(association_id)
|
27
|
-
self.class.associate_class(association_id)
|
23
|
+
instance_variable_set _t_ivar_name(association), associate
|
28
24
|
end
|
29
25
|
|
30
26
|
end
|
@@ -62,53 +62,36 @@ begin
|
|
62
62
|
find(:all, :conditions => ["#{property} = ?", id.to_s])
|
63
63
|
end
|
64
64
|
|
65
|
-
def self._t_initialize_has_many_association(
|
66
|
-
after_save { |record| record.class._t_save_associates(record,
|
65
|
+
def self._t_initialize_has_many_association(association)
|
66
|
+
after_save { |record| record.class._t_save_associates(record, association) }
|
67
67
|
end
|
68
68
|
|
69
|
-
def self._t_initialize_belongs_to_association(
|
70
|
-
before_save { |record| record.class._t_stringify_belongs_to_value(record,
|
69
|
+
def self._t_initialize_belongs_to_association(association)
|
70
|
+
before_save { |record| record.class._t_stringify_belongs_to_value(record, association) }
|
71
71
|
end
|
72
72
|
|
73
73
|
def _t_reload
|
74
74
|
reload
|
75
75
|
end
|
76
76
|
|
77
|
-
def _t_clear_associates(
|
78
|
-
|
79
|
-
self.connection.execute("delete from #{t_join_table_name} where #{self.class._t_my_id_column} = #{self.id}")
|
77
|
+
def _t_clear_associates(association)
|
78
|
+
self.connection.execute("delete from #{association.join_table} where #{association.association_key} = #{self.id}")
|
80
79
|
end
|
81
80
|
|
82
|
-
def _t_associate_many(
|
83
|
-
t_join_table_name = self.class._t_join_table_name(association_id)
|
84
|
-
values = associate_ids.map { |associate_id| "(#{self.id}, '#{associate_id}')" }.join(',')
|
85
|
-
|
81
|
+
def _t_associate_many(association, associate_ids)
|
86
82
|
self.transaction do
|
87
|
-
_t_clear_associates(
|
88
|
-
|
83
|
+
_t_clear_associates(association)
|
84
|
+
associate_ids.each do |associate_id|
|
85
|
+
self.connection.execute("insert into #{association.join_table} (#{association.association_key}, #{association.association_foreign_key}) values (#{self.id}, '#{associate_id}')")
|
86
|
+
end
|
89
87
|
end
|
90
88
|
end
|
91
89
|
|
92
|
-
def _t_get_associate_ids(
|
93
|
-
|
94
|
-
rows = self.connection.execute("select #{self.class._t_associate_id_column(association_id)} from #{t_join_table_name} where #{self.class._t_my_id_column} = #{self.id}")
|
90
|
+
def _t_get_associate_ids(association)
|
91
|
+
rows = self.connection.execute("select #{association.association_foreign_key} from #{association.join_table} where #{association.association_key} = #{self.id}")
|
95
92
|
ids = []; rows.each { |r| ids << r[0] }; ids
|
96
93
|
end
|
97
94
|
|
98
|
-
private
|
99
|
-
|
100
|
-
def self._t_my_id_column
|
101
|
-
table_name.singularize + '_id'
|
102
|
-
end
|
103
|
-
|
104
|
-
def self._t_associate_id_column(association_id)
|
105
|
-
association_id.to_s.singularize + '_id'
|
106
|
-
end
|
107
|
-
|
108
|
-
def self._t_join_table_name(association_id)
|
109
|
-
association_id.to_s < table_name ? "#{association_id}_#{table_name}" : "#{table_name}_#{association_id}"
|
110
|
-
end
|
111
|
-
|
112
95
|
end
|
113
96
|
end
|
114
97
|
rescue LoadError
|
@@ -24,10 +24,7 @@ begin
|
|
24
24
|
# == t_has_one
|
25
25
|
#
|
26
26
|
# The +t_has_one+ association will not define any new properties on the object, since
|
27
|
-
# the associated object holds the foreign key.
|
28
|
-
# is the target of a t_has_one association from another class, then a property
|
29
|
-
# named after the association will be created on the CouchRest::ExtendedDocument object to
|
30
|
-
# hold the foreign key to the other object.
|
27
|
+
# the associated object holds the foreign key.
|
31
28
|
#
|
32
29
|
#
|
33
30
|
# == t_has_many
|
@@ -25,10 +25,7 @@ begin
|
|
25
25
|
# == t_has_one
|
26
26
|
#
|
27
27
|
# The +t_has_one+ association will not define any new properties on the object, since
|
28
|
-
# the associated object holds the foreign key.
|
29
|
-
# is the target of a t_has_one association from another class, then a property
|
30
|
-
# named after the association will be created on the CouchRest::Model object to
|
31
|
-
# hold the foreign key to the other object.
|
28
|
+
# the associated object holds the foreign key.
|
32
29
|
#
|
33
30
|
#
|
34
31
|
# == t_has_many
|
@@ -23,29 +23,20 @@ module CouchRest
|
|
23
23
|
self.send("by_#{property}", :key => id.to_s)
|
24
24
|
end
|
25
25
|
|
26
|
-
def _t_initialize_has_many_association(
|
27
|
-
unless self.respond_to?(
|
28
|
-
property
|
29
|
-
view_by
|
30
|
-
after_save { |record| record.class._t_save_associates(record,
|
26
|
+
def _t_initialize_has_many_association(association)
|
27
|
+
unless self.respond_to?(association.foreign_keys_property)
|
28
|
+
property association.foreign_keys_property, :type => [String]
|
29
|
+
view_by association.foreign_keys_property
|
30
|
+
after_save { |record| record.class._t_save_associates(record, association) if record.class.respond_to?(:_t_save_associates) }
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
def _t_initialize_belongs_to_association(
|
35
|
-
property_name =
|
34
|
+
def _t_initialize_belongs_to_association(association)
|
35
|
+
property_name = association.foreign_key
|
36
36
|
unless self.respond_to?(property_name)
|
37
37
|
property property_name, :type => String
|
38
38
|
view_by property_name
|
39
|
-
before_save { |record| _t_stringify_belongs_to_value(record,
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def _t_initialize_has_one_association(association_id)
|
44
|
-
property_name = "#{association_id}_id"
|
45
|
-
unless self.respond_to?(property_name)
|
46
|
-
property property_name, :type => String
|
47
|
-
view_by property_name
|
48
|
-
before_save { |record| _t_stringify_has_one_value(record, association_id) if self.respond_to?(:_t_stringify_has_one_value) }
|
39
|
+
before_save { |record| _t_stringify_belongs_to_value(record, association) if self.respond_to?(:_t_stringify_belongs_to_value) }
|
49
40
|
end
|
50
41
|
end
|
51
42
|
end
|
@@ -6,16 +6,16 @@ module CouchRest
|
|
6
6
|
new_doc.each { |k,v| self[k] = new_doc[k] }
|
7
7
|
end
|
8
8
|
|
9
|
-
def _t_associate_many(
|
10
|
-
self.send(
|
9
|
+
def _t_associate_many(association, associate_ids)
|
10
|
+
self.send(association.foreign_keys_property + '=', associate_ids.map { |associate_id| associate_id.to_s })
|
11
11
|
end
|
12
12
|
|
13
|
-
def _t_get_associate_ids(
|
14
|
-
self.send(
|
13
|
+
def _t_get_associate_ids(association)
|
14
|
+
self.send(association.foreign_keys_property) || []
|
15
15
|
end
|
16
16
|
|
17
|
-
def _t_clear_associates(
|
18
|
-
self.send(
|
17
|
+
def _t_clear_associates(association)
|
18
|
+
self.send(association.foreign_keys_property + '=', [])
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|