composite_primary_keys 0.7.2 → 0.7.3
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/Rakefile +0 -4
- data/lib/composite_primary_keys/base.rb +145 -142
- data/lib/composite_primary_keys/version.rb +1 -1
- data/website/index.html +7 -7
- data/website/index.txt +5 -5
- data/website/version-raw.js +1 -1
- data/website/version.js +1 -1
- metadata +13 -13
data/Rakefile
CHANGED
@@ -17,10 +17,6 @@ RELEASE_NAME = "REL #{PKG_VERSION}"
|
|
17
17
|
RUBY_FORGE_PROJECT = "compositekeys"
|
18
18
|
RUBY_FORGE_USER = "nicwilliams"
|
19
19
|
|
20
|
-
PKG_FILES = FileList[
|
21
|
-
"lib/**/*", "test/**/*", "examples/**/*", "doc/**/*", "scripts/**/*", "website/**/*", "[A-Z]*", "install.rb", "CHANGELOG", "README", "Rakefile"
|
22
|
-
].exclude(/\bCVS\b|~$/)
|
23
|
-
|
24
20
|
|
25
21
|
desc "Default Task"
|
26
22
|
task :default => [ :test_mysql ] # UNTESTED =, :test_sqlite, :test_postgresql ]
|
@@ -2,18 +2,18 @@ module CompositePrimaryKeys
|
|
2
2
|
module ActiveRecord #:nodoc:
|
3
3
|
class CompositeKeyError < StandardError #:nodoc:
|
4
4
|
end
|
5
|
-
|
5
|
+
|
6
6
|
module Base #:nodoc:
|
7
|
-
|
7
|
+
|
8
8
|
INVALID_FOR_COMPOSITE_KEYS = 'Not appropriate for composite primary keys'
|
9
9
|
NOT_IMPLEMENTED_YET = 'Not implemented for composite primary keys yet'
|
10
|
-
|
10
|
+
|
11
11
|
def self.append_features(base)
|
12
12
|
super
|
13
13
|
base.send(:include, InstanceMethods)
|
14
14
|
base.extend(ClassMethods)
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
module ClassMethods
|
18
18
|
def set_primary_keys(*keys)
|
19
19
|
keys = keys.first if keys.first.is_a?(Array)
|
@@ -35,7 +35,7 @@ module CompositePrimaryKeys
|
|
35
35
|
module InstanceMethods
|
36
36
|
def composite?; self.class.composite?; end
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
module CompositeInstanceMethods
|
40
40
|
|
41
41
|
# A model instance's primary keys is always available as model.ids
|
@@ -43,7 +43,7 @@ module CompositePrimaryKeys
|
|
43
43
|
def id
|
44
44
|
attr_names = self.class.primary_keys
|
45
45
|
CompositeIds.new(
|
46
|
-
|
46
|
+
attr_names.map {|attr_name| read_attribute(attr_name)}
|
47
47
|
)
|
48
48
|
end
|
49
49
|
alias_method :ids, :id
|
@@ -53,16 +53,16 @@ module CompositePrimaryKeys
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def id_before_type_cast #:nodoc:
|
56
|
-
|
56
|
+
raise CompositeKeyError, CompositePrimaryKeys::ActiveRecord::Base::NOT_IMPLEMENTED_YET
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
def quoted_id #:nodoc:
|
60
60
|
[self.class.primary_keys, ids].
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
transpose.
|
62
|
+
map {|attr_name,id| quote(id, column_for_attribute(attr_name))}.
|
63
|
+
to_composite_ids
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
# Sets the primary ID.
|
67
67
|
def id=(ids)
|
68
68
|
ids = ids.split(ID_SEP) if ids.is_a?(String)
|
@@ -73,7 +73,7 @@ module CompositePrimaryKeys
|
|
73
73
|
[primary_keys, ids].transpose.each {|key, an_id| write_attribute(key , an_id)}
|
74
74
|
id
|
75
75
|
end
|
76
|
-
|
76
|
+
|
77
77
|
# Returns a clone of the record that hasn't been assigned an id yet and
|
78
78
|
# is treated as a new record. Note that this is a "shallow" clone:
|
79
79
|
# it copies the object's attributes only, not its associations.
|
@@ -86,7 +86,7 @@ module CompositePrimaryKeys
|
|
86
86
|
record.send :instance_variable_set, '@attributes', attrs
|
87
87
|
end
|
88
88
|
end
|
89
|
-
|
89
|
+
|
90
90
|
# Define an attribute reader method. Cope with nil column.
|
91
91
|
def define_read_method(symbol, attr_name, column)
|
92
92
|
cast_code = column.type_cast_code('v') if column
|
@@ -103,8 +103,8 @@ module CompositePrimaryKeys
|
|
103
103
|
def method_missing(method_id, *args, &block)
|
104
104
|
method_name = method_id.to_s
|
105
105
|
if @attributes.include?(method_name) or
|
106
|
-
|
107
|
-
|
106
|
+
(md = /\?$/.match(method_name) and
|
107
|
+
@attributes.include?(method_name = md.pre_match))
|
108
108
|
define_read_methods if self.class.read_methods.empty? && self.class.generate_read_methods
|
109
109
|
md ? query_attribute(method_name) : read_attribute(method_name)
|
110
110
|
elsif self.class.primary_keys.include? method_name.to_sym
|
@@ -113,10 +113,10 @@ module CompositePrimaryKeys
|
|
113
113
|
attribute_name, method_type = md.pre_match, md.to_s
|
114
114
|
if @attributes.include?(attribute_name)
|
115
115
|
case method_type
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
116
|
+
when '='
|
117
|
+
write_attribute(attribute_name, args.first)
|
118
|
+
when '_before_type_cast'
|
119
|
+
read_attribute_before_type_cast(attribute_name)
|
120
120
|
end
|
121
121
|
else
|
122
122
|
super
|
@@ -126,15 +126,15 @@ module CompositePrimaryKeys
|
|
126
126
|
end
|
127
127
|
end
|
128
128
|
|
129
|
-
|
129
|
+
private
|
130
130
|
# The xx_without_callbacks methods are overwritten as that is the end of the alias chain
|
131
|
-
|
131
|
+
|
132
132
|
# Creates a new record with values matching those of the instance attributes.
|
133
133
|
def create_without_callbacks
|
134
134
|
unless self.id
|
135
135
|
raise CompositeKeyError, "Composite keys do not generated ids from sequences, you must provide id values"
|
136
136
|
end
|
137
|
-
|
137
|
+
|
138
138
|
connection.insert(
|
139
139
|
"INSERT INTO #{self.class.table_name} " +
|
140
140
|
"(#{quoted_column_names.join(', ')}) " +
|
@@ -160,97 +160,100 @@ module CompositePrimaryKeys
|
|
160
160
|
# Deletes the record in the database and freezes this instance to reflect that no changes should
|
161
161
|
# be made (since they can't be persisted).
|
162
162
|
def destroy_without_callbacks
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
163
|
+
where_class = [self.class.primary_key, quoted_id].transpose.map do |pair|
|
164
|
+
"(#{pair[0]} = #{pair[1]})"
|
165
|
+
end.join(" AND ")
|
166
|
+
unless new_record?
|
167
|
+
connection.delete(
|
168
|
+
"DELETE FROM #{self.class.table_name} " +
|
169
|
+
"WHERE #{where_class}",
|
170
|
+
"#{self.class.name} Destroy"
|
171
|
+
)
|
172
|
+
end
|
173
|
+
freeze
|
168
174
|
end
|
169
|
-
|
170
|
-
freeze
|
175
|
+
|
171
176
|
end
|
172
|
-
|
173
|
-
end
|
174
|
-
|
175
|
-
module CompositeClassMethods
|
176
|
-
def primary_key; primary_keys; end
|
177
|
-
def primary_key=(keys); primary_keys = keys; end
|
178
177
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
178
|
+
module CompositeClassMethods
|
179
|
+
def primary_key; primary_keys; end
|
180
|
+
def primary_key=(keys); primary_keys = keys; end
|
181
|
+
|
182
|
+
def composite?
|
183
|
+
true
|
184
|
+
end
|
185
|
+
|
186
|
+
#ids_to_s([[1,2],[7,3]]) -> "(1,2),(7,3)"
|
187
|
+
#ids_to_s([[1,2],[7,3]], ',', ';') -> "1,2;7,3"
|
188
|
+
def ids_to_s(many_ids, id_sep = CompositePrimaryKeys::ID_SEP, list_sep = ',', left_bracket = '(', right_bracket = ')')
|
189
|
+
many_ids.map {|ids| "#{left_bracket}#{ids}#{right_bracket}"}.join(list_sep)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Returns true if the given +ids+ represents the primary keys of a record in the database, false otherwise.
|
193
|
+
# Example:
|
194
|
+
# Person.exists?(5,7)
|
195
|
+
def exists?(ids)
|
196
|
+
obj = find(ids) rescue false
|
194
197
|
!obj.nil? and obj.is_a?(self)
|
195
|
-
end
|
196
|
-
|
197
|
-
# Deletes the record with the given +ids+ without instantiating an object first, e.g. delete(1,2)
|
198
|
-
# If an array of ids is provided (e.g. delete([1,2], [3,4]), all of them
|
199
|
-
# are deleted.
|
200
|
-
def delete(*ids)
|
201
|
-
unless ids.is_a?(Array); raise "*ids must be an Array"; end
|
202
|
-
ids = [ids.to_composite_ids] if not ids.first.is_a?(Array)
|
203
|
-
delete_all([ "(#{primary_keys}) IN (#{ids_to_s(ids)})" ])
|
204
|
-
end
|
205
|
-
|
206
|
-
# Destroys the record with the given +ids+ by instantiating the object and calling #destroy (all the callbacks are the triggered).
|
207
|
-
# If an array of ids is provided, all of them are destroyed.
|
208
|
-
def destroy(*ids)
|
209
|
-
unless ids.is_a?(Array); raise "*ids must be an Array"; end
|
210
|
-
if ids.first.is_a?(Array)
|
211
|
-
ids = ids.map{|compids| compids.to_composite_ids}
|
212
|
-
else
|
213
|
-
ids = ids.to_composite_ids
|
214
198
|
end
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
199
|
+
|
200
|
+
# Deletes the record with the given +ids+ without instantiating an object first, e.g. delete(1,2)
|
201
|
+
# If an array of ids is provided (e.g. delete([1,2], [3,4]), all of them
|
202
|
+
# are deleted.
|
203
|
+
def delete(*ids)
|
204
|
+
unless ids.is_a?(Array); raise "*ids must be an Array"; end
|
205
|
+
ids = [ids.to_composite_ids] if not ids.first.is_a?(Array)
|
206
|
+
delete_all([ "(#{primary_keys}) IN (#{ids_to_s(ids)})" ])
|
207
|
+
end
|
208
|
+
|
209
|
+
# Destroys the record with the given +ids+ by instantiating the object and calling #destroy (all the callbacks are the triggered).
|
210
|
+
# If an array of ids is provided, all of them are destroyed.
|
211
|
+
def destroy(*ids)
|
212
|
+
unless ids.is_a?(Array); raise "*ids must be an Array"; end
|
213
|
+
if ids.first.is_a?(Array)
|
214
|
+
ids = ids.map{|compids| compids.to_composite_ids}
|
215
|
+
else
|
216
|
+
ids = ids.to_composite_ids
|
217
|
+
end
|
218
|
+
ids.first.is_a?(CompositeIds) ? ids.each { |id_set| find(id_set).destroy } : find(ids).destroy
|
225
219
|
end
|
226
|
-
@columns
|
227
|
-
end
|
228
220
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
221
|
+
# Returns an array of column objects for the table associated with this class.
|
222
|
+
# Each column that matches to one of the primary keys has its
|
223
|
+
# primary attribute set to true
|
224
|
+
def columns
|
225
|
+
unless @columns
|
226
|
+
@columns = connection.columns(table_name, "#{name} Columns")
|
227
|
+
@columns.each {|column| column.primary = primary_keys.include?(column.name.to_sym)}
|
228
|
+
end
|
229
|
+
@columns
|
230
|
+
end
|
231
|
+
|
232
|
+
## DEACTIVATED METHODS ##
|
233
|
+
public
|
234
|
+
# Lazy-set the sequence name to the connection's default. This method
|
235
|
+
# is only ever called once since set_sequence_name overrides it.
|
233
236
|
def sequence_name #:nodoc:
|
234
237
|
raise CompositeKeyError, CompositePrimaryKeys::ActiveRecord::Base::INVALID_FOR_COMPOSITE_KEYS
|
235
238
|
end
|
236
|
-
|
239
|
+
|
237
240
|
def reset_sequence_name #:nodoc:
|
238
241
|
raise CompositeKeyError, CompositePrimaryKeys::ActiveRecord::Base::INVALID_FOR_COMPOSITE_KEYS
|
239
242
|
end
|
240
|
-
|
243
|
+
|
241
244
|
def set_primary_key(value = nil, &block)
|
242
245
|
raise CompositeKeyError, CompositePrimaryKeys::ActiveRecord::Base::INVALID_FOR_COMPOSITE_KEYS
|
243
246
|
end
|
244
|
-
|
245
|
-
|
247
|
+
|
248
|
+
private
|
246
249
|
def find_one(id, options)
|
247
250
|
raise CompositeKeyError, CompositePrimaryKeys::ActiveRecord::Base::INVALID_FOR_COMPOSITE_KEYS
|
248
251
|
end
|
249
|
-
|
252
|
+
|
250
253
|
def find_some(ids, options)
|
251
254
|
raise CompositeKeyError, CompositePrimaryKeys::ActiveRecord::Base::INVALID_FOR_COMPOSITE_KEYS
|
252
255
|
end
|
253
|
-
|
256
|
+
|
254
257
|
def find_from_ids(ids, options)
|
255
258
|
conditions = " AND (#{sanitize_sql(options[:conditions])})" if options[:conditions]
|
256
259
|
# if ids is just a flat list, then its size must = primary_key.length (one id per primary key, in order)
|
@@ -279,58 +282,58 @@ module CompositePrimaryKeys
|
|
279
282
|
conditions = ids.map do |id_set|
|
280
283
|
[primary_keys, id_set].transpose.map do |key, id|
|
281
284
|
"#{table_name}.#{key.to_s}=#{sanitize(id)}"
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
285
|
+
end.join(" AND ")
|
286
|
+
end.join(") OR (")
|
287
|
+
options.update :conditions => "(#{conditions})"
|
288
|
+
|
289
|
+
result = find_every(options)
|
290
|
+
|
291
|
+
if result.size == ids.size
|
292
|
+
ids.size == 1 ? result[0] : result
|
293
|
+
else
|
294
|
+
raise RecordNotFound, "Couldn't find all #{name.pluralize} with IDs (#{ids_list})#{conditions}"
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
292
298
|
end
|
293
299
|
end
|
294
|
-
|
295
|
-
end
|
296
|
-
end
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
module ActiveRecord
|
301
|
-
ID_SEP = ','
|
302
|
-
ID_SET_SEP = ';'
|
303
|
-
|
304
|
-
class Base
|
305
|
-
# Allows +attr_name+ to be the list of primary_keys, and returns the id
|
306
|
-
# of the object
|
307
|
-
# e.g. @object[@object.class.primary_key] => [1,1]
|
308
|
-
def [](attr_name)
|
309
|
-
if attr_name.is_a?(String) and attr_name != attr_name.split(ID_SEP).first
|
310
|
-
attr_name = attr_name.split(ID_SEP)
|
311
|
-
end
|
312
|
-
attr_name.is_a?(Array) ?
|
313
|
-
attr_name.map {|name| read_attribute(name)} :
|
314
|
-
read_attribute(attr_name)
|
315
|
-
end
|
316
|
-
|
317
|
-
# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+.
|
318
|
-
# (Alias for the protected write_attribute method).
|
319
|
-
def []=(attr_name, value)
|
320
|
-
if attr_name.is_a?(String) and attr_name != attr_name.split(ID_SEP).first
|
321
|
-
attr_name = attr_name.split(ID_SEP)
|
300
|
+
end
|
322
301
|
end
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
302
|
+
|
303
|
+
module ActiveRecord
|
304
|
+
ID_SEP = ','
|
305
|
+
ID_SET_SEP = ';'
|
306
|
+
|
307
|
+
class Base
|
308
|
+
# Allows +attr_name+ to be the list of primary_keys, and returns the id
|
309
|
+
# of the object
|
310
|
+
# e.g. @object[@object.class.primary_key] => [1,1]
|
311
|
+
def [](attr_name)
|
312
|
+
if attr_name.is_a?(String) and attr_name != attr_name.split(ID_SEP).first
|
313
|
+
attr_name = attr_name.split(ID_SEP)
|
314
|
+
end
|
315
|
+
attr_name.is_a?(Array) ?
|
316
|
+
attr_name.map {|name| read_attribute(name)} :
|
317
|
+
read_attribute(attr_name)
|
318
|
+
end
|
319
|
+
|
320
|
+
# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+.
|
321
|
+
# (Alias for the protected write_attribute method).
|
322
|
+
def []=(attr_name, value)
|
323
|
+
if attr_name.is_a?(String) and attr_name != attr_name.split(ID_SEP).first
|
324
|
+
attr_name = attr_name.split(ID_SEP)
|
325
|
+
end
|
326
|
+
if attr_name.is_a? Array
|
327
|
+
value = value.split(ID_SEP) if value.is_a? String
|
328
|
+
unless value.length == attr_name.length
|
329
|
+
raise "Number of attr_names and values do not match"
|
330
|
+
end
|
331
|
+
#breakpoint
|
332
|
+
[attr_name, value].transpose.map {|name,val| write_attribute(name.to_s, val)}
|
333
|
+
else
|
334
|
+
write_attribute(attr_name, value)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
327
338
|
end
|
328
|
-
#breakpoint
|
329
|
-
[attr_name, value].transpose.map {|name,val| write_attribute(name.to_s, val)}
|
330
|
-
else
|
331
|
-
write_attribute(attr_name, value)
|
332
339
|
end
|
333
|
-
end
|
334
|
-
|
335
|
-
end
|
336
|
-
end
|
data/website/index.html
CHANGED
@@ -33,7 +33,7 @@
|
|
33
33
|
<h1>Composite Primary Keys for Ruby on Rails/ActiveRecords</h1>
|
34
34
|
<div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/compositekeys"; return false'>
|
35
35
|
Get Version
|
36
|
-
<a href="http://rubyforge.org/projects/compositekeys" class="numbers">0.7.
|
36
|
+
<a href="http://rubyforge.org/projects/compositekeys" class="numbers">0.7.3</a>
|
37
37
|
</div>
|
38
38
|
<h2>What</h2>
|
39
39
|
|
@@ -120,11 +120,11 @@ associations allow for composite foreign keys.</p>
|
|
120
120
|
<span class="keyword">class </span><span class="class">ProductTariff</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
|
121
121
|
<span class="ident">set_primary_keys</span> <span class="symbol">:product_id</span><span class="punct">,</span> <span class="symbol">:tariff_id</span><span class="punct">,</span> <span class="symbol">:tariff_start_date</span>
|
122
122
|
<span class="ident">belongs_to</span> <span class="symbol">:products</span><span class="punct">,</span> <span class="symbol">:foreign_key</span> <span class="punct">=></span> <span class="symbol">:product_id</span>
|
123
|
-
<span class="ident">belongs_to</span> <span class="symbol">:tariffs</span><span class="punct">,</span> <span class="symbol">:
|
123
|
+
<span class="ident">belongs_to</span> <span class="symbol">:tariffs</span><span class="punct">,</span> <span class="symbol">:foreign_key</span> <span class="punct">=></span> <span class="punct">[</span><span class="symbol">:tariff_id</span><span class="punct">,</span> <span class="symbol">:tariff_start_date</span><span class="punct">]</span>
|
124
124
|
<span class="keyword">end</span>
|
125
125
|
<span class="keyword">class </span><span class="class">Tariff</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
|
126
126
|
<span class="ident">set_primary_keys</span> <span class="punct">[</span><span class="symbol">:tariff_id</span><span class="punct">,</span> <span class="symbol">:start_date</span><span class="punct">]</span>
|
127
|
-
<span class="ident">has_many</span> <span class="symbol">:product_tariffs</span><span class="punct">,</span> <span class="symbol">:
|
127
|
+
<span class="ident">has_many</span> <span class="symbol">:product_tariffs</span><span class="punct">,</span> <span class="symbol">:foreign_key</span> <span class="punct">=></span> <span class="punct">[</span><span class="symbol">:tariff_id</span><span class="punct">,</span> <span class="symbol">:tariff_start_date</span><span class="punct">]</span>
|
128
128
|
<span class="keyword">end</span>
|
129
129
|
</pre></p>
|
130
130
|
|
@@ -134,9 +134,9 @@ associations allow for composite foreign keys.</p>
|
|
134
134
|
(called :tariffs) must use a composite foreign key.</p>
|
135
135
|
|
136
136
|
|
137
|
-
<p>The expression
|
138
|
-
|
139
|
-
columns. If the column names in both tables match, then the :foreign_key
|
137
|
+
<p>The expression must use the :foreign_key option (NOTE, <code>:foreign_keys</code> is not currently supported)
|
138
|
+
to specific the ordered list of table
|
139
|
+
columns. If the column names in both tables match, then the :foreign_key
|
140
140
|
option can be omitted.</p>
|
141
141
|
|
142
142
|
|
@@ -185,7 +185,7 @@ other stories and things.</p>
|
|
185
185
|
|
186
186
|
<p>Comments are welcome. Send an email to <a href="mailto:drnicwilliams@gmail.com">Dr Nic Williams</a>.</p>
|
187
187
|
<p class="coda">
|
188
|
-
<a href="mailto:drnicwilliams@gmail.com">Dr Nic</a>,
|
188
|
+
<a href="mailto:drnicwilliams@gmail.com">Dr Nic</a>, 24th October 2006<br>
|
189
189
|
Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
|
190
190
|
</p>
|
191
191
|
</div>
|
data/website/index.txt
CHANGED
@@ -71,11 +71,11 @@ end
|
|
71
71
|
class ProductTariff < ActiveRecord::Base
|
72
72
|
set_primary_keys :product_id, :tariff_id, :tariff_start_date
|
73
73
|
belongs_to :products, :foreign_key => :product_id
|
74
|
-
belongs_to :tariffs, :
|
74
|
+
belongs_to :tariffs, :foreign_key => [:tariff_id, :tariff_start_date]
|
75
75
|
end
|
76
76
|
class Tariff < ActiveRecord::Base
|
77
77
|
set_primary_keys [:tariff_id, :start_date]
|
78
|
-
has_many :product_tariffs, :
|
78
|
+
has_many :product_tariffs, :foreign_key => [:tariff_id, :tariff_start_date]
|
79
79
|
end
|
80
80
|
</pre>
|
81
81
|
|
@@ -83,9 +83,9 @@ The Tariff table has a composite primary key. Hence, the
|
|
83
83
|
<code syntax="ruby">belongs_to</code> association from ProductTariff to Tariff
|
84
84
|
(called :tariffs) must use a composite foreign key.
|
85
85
|
|
86
|
-
The expression
|
87
|
-
|
88
|
-
columns. If the column names in both tables match, then the :foreign_key
|
86
|
+
The expression must use the :foreign_key option (NOTE, <code>:foreign_keys</code> is not currently supported)
|
87
|
+
to specific the ordered list of table
|
88
|
+
columns. If the column names in both tables match, then the :foreign_key
|
89
89
|
option can be omitted.
|
90
90
|
|
91
91
|
Similarly, the <code syntax="ruby">has_many</code> and <code syntax="ruby">has_one</code>
|
data/website/version-raw.js
CHANGED
data/website/version.js
CHANGED
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: composite_primary_keys
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.7.
|
7
|
-
date: 2006-09
|
6
|
+
version: 0.7.3
|
7
|
+
date: 2006-11-09 00:00:00 +01:00
|
8
8
|
summary: Support for composite primary keys in ActiveRecords
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -32,16 +32,14 @@ files:
|
|
32
32
|
- install.rb
|
33
33
|
- README
|
34
34
|
- CHANGELOG
|
35
|
-
- lib/composite_primary_keys
|
36
35
|
- lib/composite_primary_keys.rb
|
36
|
+
- lib/composite_primary_keys
|
37
37
|
- lib/composite_primary_keys/composite_arrays.rb
|
38
38
|
- lib/composite_primary_keys/version.rb
|
39
39
|
- lib/composite_primary_keys/base.rb
|
40
40
|
- lib/composite_primary_keys/fixtures.rb
|
41
41
|
- lib/composite_primary_keys/reflection.rb
|
42
42
|
- lib/composite_primary_keys/associations.rb
|
43
|
-
- test/connections
|
44
|
-
- test/fixtures
|
45
43
|
- test/composite_arrays_test.rb
|
46
44
|
- test/hash_tricks.rb
|
47
45
|
- test/delete_test.rb
|
@@ -57,15 +55,12 @@ files:
|
|
57
55
|
- test/attributes_test.rb
|
58
56
|
- test/create_test.rb
|
59
57
|
- test/santiago_test.rb
|
60
|
-
- test/
|
61
|
-
- test/connections
|
62
|
-
- test/connections/native_mysql/connection.rb
|
63
|
-
- test/connections/native_oracle/connection.rb
|
58
|
+
- test/fixtures
|
59
|
+
- test/connections
|
64
60
|
- test/fixtures/reference_type.rb
|
65
61
|
- test/fixtures/reference_code.rb
|
66
62
|
- test/fixtures/reference_types.yml
|
67
63
|
- test/fixtures/reference_codes.yml
|
68
|
-
- test/fixtures/db_definitions
|
69
64
|
- test/fixtures/product.rb
|
70
65
|
- test/fixtures/product_tariff.rb
|
71
66
|
- test/fixtures/tariff.rb
|
@@ -82,20 +77,25 @@ files:
|
|
82
77
|
- test/fixtures/articles.yml
|
83
78
|
- test/fixtures/users.yml
|
84
79
|
- test/fixtures/readings.yml
|
80
|
+
- test/fixtures/db_definitions
|
85
81
|
- test/fixtures/db_definitions/mysql.drop.sql
|
86
82
|
- test/fixtures/db_definitions/mysql.sql
|
83
|
+
- test/connections/native_oracle
|
84
|
+
- test/connections/native_mysql
|
85
|
+
- test/connections/native_oracle/connection.rb
|
86
|
+
- test/connections/native_mysql/connection.rb
|
87
87
|
- website/index.txt
|
88
88
|
- website/template.rhtml
|
89
|
-
- website/stylesheets
|
90
|
-
- website/javascripts
|
91
89
|
- website/index.html
|
92
90
|
- website/version.js
|
93
91
|
- website/template.js
|
94
92
|
- website/version.txt
|
95
93
|
- website/version-raw.js
|
96
94
|
- website/version-raw.txt
|
97
|
-
- website/
|
95
|
+
- website/javascripts
|
96
|
+
- website/stylesheets
|
98
97
|
- website/javascripts/rounded_corners_lite.inc.js
|
98
|
+
- website/stylesheets/screen.css
|
99
99
|
- scripts/rubyforge-orig
|
100
100
|
- scripts/rubyforge
|
101
101
|
- scripts/http-access2-2.0.6.gem
|