tenacity 0.1.1 → 0.2.0
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.
- 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
|