composite_primary_keys 0.1.4 → 0.3.1
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 +11 -27
- data/lib/composite_primary_keys.rb +1 -0
- data/lib/composite_primary_keys/base.rb +63 -22
- data/lib/composite_primary_keys/composite_arrays.rb +28 -0
- data/lib/composite_primary_keys/version.rb +3 -3
- data/test/abstract_unit.rb +4 -3
- data/test/clone_test.rb +35 -0
- data/test/composite_arrays_test.rb +46 -0
- data/test/delete_test.rb +67 -0
- data/test/dummy_test.rb +19 -1
- data/test/find_test.rb +7 -9
- data/test/hash_tricks.rb +34 -0
- data/test/ids_test.rb +59 -0
- data/test/miscellaneous_test.rb +17 -15
- data/test/pagination_test.rb +9 -4
- data/test/update_test.rb +41 -0
- metadata +15 -10
- data/lib/composite_primary_keys/primary_keys.rb +0 -10
- data/test/primary_keys_test.rb +0 -20
data/Rakefile
CHANGED
@@ -9,7 +9,7 @@ require File.join(File.dirname(__FILE__), 'lib', 'composite_primary_keys', 'vers
|
|
9
9
|
|
10
10
|
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
|
11
11
|
PKG_NAME = 'composite_primary_keys'
|
12
|
-
PKG_VERSION =
|
12
|
+
PKG_VERSION = CompositePrimaryKeys::VERSION::STRING + PKG_BUILD
|
13
13
|
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
14
14
|
|
15
15
|
RELEASE_NAME = "REL #{PKG_VERSION}"
|
@@ -24,6 +24,7 @@ PKG_FILES = FileList[
|
|
24
24
|
|
25
25
|
desc "Default Task"
|
26
26
|
task :default => [ :test_mysql ] # UNTESTED =, :test_sqlite, :test_postgresql ]
|
27
|
+
task :test => [ :test_mysql ]
|
27
28
|
|
28
29
|
# Run the unit tests
|
29
30
|
|
@@ -38,18 +39,15 @@ end
|
|
38
39
|
SCHEMA_PATH = File.join(File.dirname(__FILE__), *%w(test fixtures db_definitions))
|
39
40
|
|
40
41
|
desc 'Build the MySQL test databases'
|
41
|
-
task :build_mysql_databases
|
42
|
+
task :build_mysql_databases do
|
42
43
|
puts File.join(SCHEMA_PATH, 'mysql.sql')
|
43
|
-
%x( mysqladmin -u root create
|
44
|
-
|
45
|
-
%x( mysql -u root activerecord_unittest < #{File.join(SCHEMA_PATH, 'mysql.sql')} )
|
46
|
-
#%x( mysql -u root activerecord_unittest < #{File.join(SCHEMA_PATH, 'mysql2.sql')} )
|
44
|
+
%x( mysqladmin -u root create "#{PKG_NAME}_unittest" )
|
45
|
+
%x( mysql -u root "#{PKG_NAME}_unittest" < #{File.join(SCHEMA_PATH, 'mysql.sql')} )
|
47
46
|
end
|
48
47
|
|
49
48
|
desc 'Drop the MySQL test databases'
|
50
49
|
task :drop_mysql_databases do
|
51
|
-
%x( mysqladmin -u root -f drop
|
52
|
-
#%x( mysqladmin -u root -f drop activerecord_unittest2 )
|
50
|
+
%x( mysqladmin -u root -f drop "#{PKG_NAME}_unittest" )
|
53
51
|
end
|
54
52
|
|
55
53
|
desc 'Rebuild the MySQL test databases'
|
@@ -57,16 +55,13 @@ task :rebuild_mysql_databases => [:drop_mysql_databases, :build_mysql_databases]
|
|
57
55
|
|
58
56
|
desc 'Build the PostgreSQL test databases'
|
59
57
|
task :build_postgresql_databases do
|
60
|
-
%x( createdb
|
61
|
-
%x(
|
62
|
-
%x( psql activerecord_unittest -f #{File.join(SCHEMA_PATH, 'postgresql.sql')} )
|
63
|
-
%x( psql activerecord_unittest2 -f #{File.join(SCHEMA_PATH, 'postgresql2.sql')} )
|
58
|
+
%x( createdb "#{PKG_NAME}_unittest" )
|
59
|
+
%x( psql "#{PKG_NAME}_unittest" -f #{File.join(SCHEMA_PATH, 'postgresql.sql')} )
|
64
60
|
end
|
65
61
|
|
66
62
|
desc 'Drop the PostgreSQL test databases'
|
67
63
|
task :drop_postgresql_databases do
|
68
|
-
%x( dropdb
|
69
|
-
%x( dropdb activerecord_unittest2 )
|
64
|
+
%x( dropdb "#{PKG_NAME}_unittest" )
|
70
65
|
end
|
71
66
|
|
72
67
|
desc 'Rebuild the PostgreSQL test databases'
|
@@ -117,8 +112,8 @@ spec = Gem::Specification.new do |s|
|
|
117
112
|
|
118
113
|
s.author = "Dr Nic Williams"
|
119
114
|
s.email = "drnicwilliams@gmail.com"
|
120
|
-
s.homepage = "http://
|
121
|
-
s.rubyforge_project = "
|
115
|
+
s.homepage = "http://compositekeys.rubyforge.org"
|
116
|
+
s.rubyforge_project = "compositekeys"
|
122
117
|
end
|
123
118
|
|
124
119
|
Rake::GemPackageTask.new(spec) do |p|
|
@@ -154,17 +149,6 @@ end
|
|
154
149
|
|
155
150
|
# Publishing ------------------------------------------------------
|
156
151
|
|
157
|
-
desc "Publish the beta gem"
|
158
|
-
task :pgem => [:package] do
|
159
|
-
Rake::SshFilePublisher.new("drnicwilliams@gmail.com", "public_html/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
|
160
|
-
`ssh drnicwilliams@gmail.com './gemupdate.sh'`
|
161
|
-
end
|
162
|
-
|
163
|
-
desc "Publish the API documentation"
|
164
|
-
task :pdoc => [:rdoc] do
|
165
|
-
Rake::SshDirPublisher.new("drnicwilliams@gmail.com", "public_html/ar", "doc").upload
|
166
|
-
end
|
167
|
-
|
168
152
|
desc "Publish the release files to RubyForge."
|
169
153
|
task :release => [ :package ] do
|
170
154
|
`ruby scripts/rubyforge login`
|
@@ -3,6 +3,7 @@ module CompositePrimaryKeys
|
|
3
3
|
module Base #:nodoc:
|
4
4
|
|
5
5
|
INVALID_FOR_COMPOSITE_KEYS = 'Not appropriate for composite primary keys'
|
6
|
+
NOT_IMPLEMENTED_YET = 'Not implemented for composite primary keys yet'
|
6
7
|
|
7
8
|
def self.append_features(base)
|
8
9
|
super
|
@@ -12,8 +13,9 @@ module CompositePrimaryKeys
|
|
12
13
|
|
13
14
|
module ClassMethods
|
14
15
|
def set_primary_keys(*keys)
|
16
|
+
keys = keys.first if keys.first.is_a?(Array) or keys.first.is_a?(CompositeKeys)
|
15
17
|
cattr_accessor :primary_keys
|
16
|
-
self.primary_keys =
|
18
|
+
self.primary_keys = keys.to_composite_keys
|
17
19
|
|
18
20
|
class_eval <<-EOV
|
19
21
|
include CompositePrimaryKeys::ActiveRecord::Base::CompositeInstanceMethods
|
@@ -38,29 +40,22 @@ module CompositePrimaryKeys
|
|
38
40
|
# whether you name it the default 'id' or set it to something else.
|
39
41
|
def id
|
40
42
|
attr_names = self.class.primary_keys
|
41
|
-
|
43
|
+
CompositeIds.new(
|
44
|
+
attr_names.map {|attr_name| read_attribute(attr_name)}
|
45
|
+
)
|
42
46
|
end
|
43
47
|
alias_method :ids, :id
|
48
|
+
alias_method :to_param, :id
|
44
49
|
|
45
|
-
#id_to_s([1,2]) -> "1,2"
|
46
|
-
#id_to_s([1,2], '-') -> "1-2"
|
47
|
-
def id_to_s(ids, id_sep = CompositePrimaryKeys::ID_SEP)
|
48
|
-
ids.map{|id| self.class.sanitize(id)}.join("#{id_sep}")
|
49
|
-
end
|
50
|
-
|
51
|
-
# Enables Active Record objects to be used as URL parameters in Action Pack automatically.
|
52
|
-
def to_param
|
53
|
-
id_to_s(ids)
|
54
|
-
end
|
55
|
-
|
56
50
|
def id_before_type_cast #:nodoc:
|
57
|
-
|
58
|
-
read_attribute_before_type_cast(self.class.primary_key)
|
51
|
+
raise CompositePrimaryKeys::ActiveRecord::Base::NOT_IMPLEMENTED_YET
|
59
52
|
end
|
60
53
|
|
61
54
|
def quoted_id #:nodoc:
|
62
|
-
|
63
|
-
|
55
|
+
[self.class.primary_keys, ids].
|
56
|
+
transpose.
|
57
|
+
map {|attr_name,id| quote(id, column_for_attribute(attr_name))}.
|
58
|
+
to_composite_ids
|
64
59
|
end
|
65
60
|
|
66
61
|
# Sets the primary ID.
|
@@ -71,7 +66,33 @@ module CompositePrimaryKeys
|
|
71
66
|
end
|
72
67
|
ids.each {|id| write_attribute(self.class.primary_key , id)}
|
73
68
|
end
|
74
|
-
|
69
|
+
|
70
|
+
# Deletes the record in the database and freezes this instance to reflect that no changes should
|
71
|
+
# be made (since they can't be persisted).
|
72
|
+
def destroy
|
73
|
+
unless new_record?
|
74
|
+
connection.delete <<-end_sql, "#{self.class.name} Destroy"
|
75
|
+
DELETE FROM #{self.class.table_name}
|
76
|
+
WHERE (#{self.class.primary_key}) = (#{quoted_id})
|
77
|
+
end_sql
|
78
|
+
end
|
79
|
+
|
80
|
+
freeze
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns a clone of the record that hasn't been assigned an id yet and
|
84
|
+
# is treated as a new record. Note that this is a "shallow" clone:
|
85
|
+
# it copies the object's attributes only, not its associations.
|
86
|
+
# The extent of a "deep" clone is application-specific and is therefore
|
87
|
+
# left to the application to implement according to its need.
|
88
|
+
def clone
|
89
|
+
attrs = self.attributes_before_type_cast
|
90
|
+
self.class.primary_keys.each {|key| attrs.delete(key.to_s)}
|
91
|
+
self.class.new do |record|
|
92
|
+
record.send :instance_variable_set, '@attributes', attrs
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
75
96
|
# Define an attribute reader method. Cope with nil column.
|
76
97
|
def define_read_method(symbol, attr_name, column)
|
77
98
|
cast_code = column.type_cast_code('v') if column
|
@@ -110,6 +131,18 @@ module CompositePrimaryKeys
|
|
110
131
|
super
|
111
132
|
end
|
112
133
|
end
|
134
|
+
|
135
|
+
private
|
136
|
+
# Updates the associated record with values matching those of the instance attributes.
|
137
|
+
def update
|
138
|
+
connection.update(
|
139
|
+
"UPDATE #{self.class.table_name} " +
|
140
|
+
"SET #{quoted_comma_pair_list(connection, attributes_with_quotes(false))} " +
|
141
|
+
"WHERE (#{self.class.primary_key}) = (#{id})",
|
142
|
+
"#{self.class.name} Update"
|
143
|
+
)
|
144
|
+
return true
|
145
|
+
end
|
113
146
|
end
|
114
147
|
|
115
148
|
module CompositeClassMethods
|
@@ -121,9 +154,9 @@ module CompositePrimaryKeys
|
|
121
154
|
end
|
122
155
|
|
123
156
|
#ids_to_s([[1,2],[7,3]]) -> "(1,2),(7,3)"
|
124
|
-
#ids_to_s([[1,2],[7,3]], ',', ';'
|
125
|
-
def ids_to_s(
|
126
|
-
|
157
|
+
#ids_to_s([[1,2],[7,3]], ',', ';') -> "1,2;7,3"
|
158
|
+
def ids_to_s(many_ids, id_sep = CompositePrimaryKeys::ID_SEP, list_sep = ',', left_bracket = '(', right_bracket = ')')
|
159
|
+
many_ids.map {|ids| "#{left_bracket}#{ids}#{right_bracket}"}.join(list_sep)
|
127
160
|
end
|
128
161
|
|
129
162
|
# Returns true if the given +ids+ represents the primary keys of a record in the database, false otherwise.
|
@@ -138,13 +171,21 @@ module CompositePrimaryKeys
|
|
138
171
|
# If an array of ids is provided (e.g. delete([1,2], [3,4]), all of them
|
139
172
|
# are deleted.
|
140
173
|
def delete(*ids)
|
174
|
+
unless ids.is_a?(Array); raise "*ids must be an Array"; end
|
175
|
+
ids = [ids.to_composite_ids] if not ids.first.is_a?(Array)
|
141
176
|
delete_all([ "(#{primary_keys}) IN (#{ids_to_s(ids)})" ])
|
142
177
|
end
|
143
178
|
|
144
179
|
# Destroys the record with the given +ids+ by instantiating the object and calling #destroy (all the callbacks are the triggered).
|
145
180
|
# If an array of ids is provided, all of them are destroyed.
|
146
181
|
def destroy(*ids)
|
147
|
-
ids.
|
182
|
+
unless ids.is_a?(Array); raise "*ids must be an Array"; end
|
183
|
+
if ids.first.is_a?(Array)
|
184
|
+
ids = ids.map{|compids| compids.to_composite_ids}
|
185
|
+
else
|
186
|
+
ids = ids.to_composite_ids
|
187
|
+
end
|
188
|
+
ids.first.is_a?(CompositeIds) ? ids.each { |id_set| find(id_set).destroy } : find(ids).destroy
|
148
189
|
end
|
149
190
|
|
150
191
|
# Returns an array of column objects for the table associated with this class.
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module CompositePrimaryKeys
|
2
|
+
ID_SEP = ','
|
3
|
+
module ArrayExtension
|
4
|
+
def to_composite_keys
|
5
|
+
CompositeKeys.new(self)
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_composite_ids
|
9
|
+
CompositeIds.new(self)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class CompositeArray < Array
|
14
|
+
def to_s
|
15
|
+
join(ID_SEP)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class CompositeKeys < CompositeArray
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
class CompositeIds < CompositeArray
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Array.send(:include, CompositePrimaryKeys::ArrayExtension)
|
data/test/abstract_unit.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
-
$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib')
|
3
2
|
|
4
3
|
require 'test/unit'
|
4
|
+
require 'hash_tricks'
|
5
5
|
require 'active_record'
|
6
6
|
require 'active_record/fixtures'
|
7
7
|
require 'active_support/binding_of_caller'
|
@@ -15,7 +15,7 @@ QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type') unless Obj
|
|
15
15
|
class Test::Unit::TestCase #:nodoc:
|
16
16
|
self.fixture_path = File.dirname(__FILE__) + "/fixtures/"
|
17
17
|
self.use_instantiated_fixtures = false
|
18
|
-
self.use_transactional_fixtures = (ENV['AR_NO_TX_FIXTURES'] != "yes")
|
18
|
+
self.use_transactional_fixtures = true #(ENV['AR_NO_TX_FIXTURES'] != "yes")
|
19
19
|
|
20
20
|
def create_fixtures(*table_names, &block)
|
21
21
|
Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures/", table_names, {}, &block)
|
@@ -55,7 +55,8 @@ protected
|
|
55
55
|
|
56
56
|
def testing_with(&block)
|
57
57
|
classes.keys.each do |@key_test|
|
58
|
-
@
|
58
|
+
@klass_info = classes[@key_test]
|
59
|
+
@klass, @primary_keys = @klass_info[:class], @klass_info[:primary_keys]
|
59
60
|
@first = @klass.find_first
|
60
61
|
yield
|
61
62
|
end
|
data/test/clone_test.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
require 'fixtures/reference_type'
|
3
|
+
require 'fixtures/reference_code'
|
4
|
+
|
5
|
+
class CloneTest < Test::Unit::TestCase
|
6
|
+
fixtures :reference_types, :reference_codes
|
7
|
+
|
8
|
+
CLASSES = {
|
9
|
+
:single => {
|
10
|
+
:class => ReferenceType,
|
11
|
+
:primary_keys => [:reference_type_id],
|
12
|
+
},
|
13
|
+
:dual => {
|
14
|
+
:class => ReferenceCode,
|
15
|
+
:primary_keys => [:reference_type_id, :reference_code],
|
16
|
+
},
|
17
|
+
}
|
18
|
+
|
19
|
+
def setup
|
20
|
+
super
|
21
|
+
self.class.classes = CLASSES
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_truth
|
25
|
+
testing_with do
|
26
|
+
clone = @first.clone
|
27
|
+
assert_equal @first.attributes.block(@klass.primary_key), clone.attributes
|
28
|
+
if composite?
|
29
|
+
@klass.primary_key.each {|key| assert_nil clone[key], "Primary key '#{key}' should be nil"}
|
30
|
+
else
|
31
|
+
assert_nil clone[@klass.primary_key], "Sole primary key should be nil"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
require 'fixtures/reference_type'
|
3
|
+
require 'fixtures/reference_code'
|
4
|
+
|
5
|
+
class CompositeArraysTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def test_new_primary_keys
|
8
|
+
keys = CompositePrimaryKeys::CompositeKeys.new
|
9
|
+
assert_not_nil keys
|
10
|
+
assert_equal '', keys.to_s
|
11
|
+
assert_equal '', "#{keys}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_initialize_primary_keys
|
15
|
+
keys = CompositePrimaryKeys::CompositeKeys.new([1,2,3])
|
16
|
+
assert_not_nil keys
|
17
|
+
assert_equal '1,2,3', keys.to_s
|
18
|
+
assert_equal '1,2,3', "#{keys}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_to_composite_keys
|
22
|
+
keys = [1,2,3].to_composite_keys
|
23
|
+
assert_equal CompositePrimaryKeys::CompositeKeys, keys.class
|
24
|
+
assert_equal '1,2,3', keys.to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_new_ids
|
28
|
+
keys = CompositePrimaryKeys::CompositeIds.new
|
29
|
+
assert_not_nil keys
|
30
|
+
assert_equal '', keys.to_s
|
31
|
+
assert_equal '', "#{keys}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_initialize_ids
|
35
|
+
keys = CompositePrimaryKeys::CompositeIds.new([1,2,3])
|
36
|
+
assert_not_nil keys
|
37
|
+
assert_equal '1,2,3', keys.to_s
|
38
|
+
assert_equal '1,2,3', "#{keys}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_to_composite_ids
|
42
|
+
keys = [1,2,3].to_composite_ids
|
43
|
+
assert_equal CompositePrimaryKeys::CompositeIds, keys.class
|
44
|
+
assert_equal '1,2,3', keys.to_s
|
45
|
+
end
|
46
|
+
end
|
data/test/delete_test.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
require 'fixtures/reference_type'
|
3
|
+
require 'fixtures/reference_code'
|
4
|
+
|
5
|
+
class DeleteTest < Test::Unit::TestCase
|
6
|
+
fixtures :reference_types, :reference_codes
|
7
|
+
|
8
|
+
CLASSES = {
|
9
|
+
:single => {
|
10
|
+
:class => ReferenceType,
|
11
|
+
:primary_keys => [:reference_type_id],
|
12
|
+
},
|
13
|
+
:dual => {
|
14
|
+
:class => ReferenceCode,
|
15
|
+
:primary_keys => [:reference_type_id, :reference_code],
|
16
|
+
},
|
17
|
+
}
|
18
|
+
|
19
|
+
def setup
|
20
|
+
super
|
21
|
+
self.class.classes = CLASSES
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_destroy_one
|
25
|
+
testing_with do
|
26
|
+
#assert @first.destroy
|
27
|
+
assert true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_destroy_one_via_class
|
32
|
+
testing_with do
|
33
|
+
assert @klass.destroy(*@first.id)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_destroy_one_alone_via_class
|
38
|
+
testing_with do
|
39
|
+
assert @klass.destroy(@first.id)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_delete_one
|
44
|
+
testing_with do
|
45
|
+
assert @klass.delete(*@first.id) if composite?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_delete_one_alone
|
50
|
+
testing_with do
|
51
|
+
assert @klass.delete(@first.id)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_delete_many
|
56
|
+
testing_with do
|
57
|
+
to_delete = @klass.find(:all)[0..1]
|
58
|
+
assert_equal 2, to_delete.length
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_delete_all
|
63
|
+
testing_with do
|
64
|
+
@klass.delete_all
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/test/dummy_test.rb
CHANGED
@@ -3,8 +3,26 @@ require 'fixtures/reference_type'
|
|
3
3
|
require 'fixtures/reference_code'
|
4
4
|
|
5
5
|
class DummyTest < Test::Unit::TestCase
|
6
|
+
fixtures :reference_types, :reference_codes
|
6
7
|
|
8
|
+
CLASSES = {
|
9
|
+
:single => {
|
10
|
+
:class => ReferenceType,
|
11
|
+
:primary_keys => [:reference_type_id],
|
12
|
+
},
|
13
|
+
:dual => {
|
14
|
+
:class => ReferenceCode,
|
15
|
+
:primary_keys => [:reference_type_id, :reference_code],
|
16
|
+
},
|
17
|
+
}
|
18
|
+
|
19
|
+
def setup
|
20
|
+
self.class.classes = CLASSES
|
21
|
+
end
|
22
|
+
|
7
23
|
def test_truth
|
8
|
-
|
24
|
+
testing_with do
|
25
|
+
assert true
|
26
|
+
end
|
9
27
|
end
|
10
28
|
end
|
data/test/find_test.rb
CHANGED
@@ -6,7 +6,7 @@ require 'fixtures/reference_code'
|
|
6
6
|
class FindTest < Test::Unit::TestCase
|
7
7
|
fixtures :reference_types, :reference_codes
|
8
8
|
|
9
|
-
|
9
|
+
CLASSES = {
|
10
10
|
:single => {
|
11
11
|
:class => ReferenceType,
|
12
12
|
:primary_keys => [:reference_type_id],
|
@@ -14,9 +14,14 @@ class FindTest < Test::Unit::TestCase
|
|
14
14
|
:dual => {
|
15
15
|
:class => ReferenceCode,
|
16
16
|
:primary_keys => [:reference_type_id, :reference_code],
|
17
|
-
}
|
17
|
+
},
|
18
18
|
}
|
19
19
|
|
20
|
+
def setup
|
21
|
+
super
|
22
|
+
self.class.classes = CLASSES
|
23
|
+
end
|
24
|
+
|
20
25
|
def test_find_first
|
21
26
|
testing_with do
|
22
27
|
obj = @klass.find_first
|
@@ -25,18 +30,11 @@ class FindTest < Test::Unit::TestCase
|
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
28
|
-
def test_ids
|
29
|
-
testing_with do
|
30
|
-
assert_equal @first.id, @first.ids if composite?
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
33
|
def test_find
|
35
34
|
testing_with do
|
36
35
|
found = @klass.find(*first_id) # e.g. find(1,1) or find 1,1
|
37
36
|
assert found
|
38
37
|
assert_equal @klass, found.class
|
39
|
-
#breakpoint
|
40
38
|
assert_equal found, @klass.find(found.id)
|
41
39
|
assert_equal found, @klass.find(found.to_param)
|
42
40
|
end
|
data/test/hash_tricks.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# From:
|
2
|
+
# http://www.bigbold.com/snippets/posts/show/2178
|
3
|
+
# http://blog.caboo.se/articles/2006/06/11/stupid-hash-tricks
|
4
|
+
#
|
5
|
+
# An example utilisation of these methods in a controller is:
|
6
|
+
# def some_action
|
7
|
+
# # some script kiddie also passed in :bee, which we don't want tampered with _here_.
|
8
|
+
# @model = Model.create(params.pass(:foo, :bar))
|
9
|
+
# end
|
10
|
+
class Hash
|
11
|
+
|
12
|
+
# lets through the keys in the argument
|
13
|
+
# >> {:one => 1, :two => 2, :three => 3}.pass(:one)
|
14
|
+
# => {:one=>1}
|
15
|
+
def pass(*keys)
|
16
|
+
keys = keys.first if keys.first.is_a?(Array)
|
17
|
+
tmp = self.clone
|
18
|
+
tmp.delete_if {|k,v| ! keys.include?(k.to_sym) }
|
19
|
+
tmp.delete_if {|k,v| ! keys.include?(k.to_s) }
|
20
|
+
tmp
|
21
|
+
end
|
22
|
+
|
23
|
+
# blocks the keys in the arguments
|
24
|
+
# >> {:one => 1, :two => 2, :three => 3}.block(:one)
|
25
|
+
# => {:two=>2, :three=>3}
|
26
|
+
def block(*keys)
|
27
|
+
keys = keys.first if keys.first.is_a?(Array)
|
28
|
+
tmp = self.clone
|
29
|
+
tmp.delete_if {|k,v| keys.include?(k.to_sym) }
|
30
|
+
tmp.delete_if {|k,v| keys.include?(k.to_s) }
|
31
|
+
tmp
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/test/ids_test.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
require 'fixtures/reference_type'
|
3
|
+
require 'fixtures/reference_code'
|
4
|
+
|
5
|
+
class IdsTest < Test::Unit::TestCase
|
6
|
+
fixtures :reference_types, :reference_codes
|
7
|
+
|
8
|
+
CLASSES = {
|
9
|
+
:single => {
|
10
|
+
:class => ReferenceType,
|
11
|
+
:primary_keys => [:reference_type_id],
|
12
|
+
},
|
13
|
+
:dual => {
|
14
|
+
:class => ReferenceCode,
|
15
|
+
:primary_keys => [:reference_type_id, :reference_code],
|
16
|
+
},
|
17
|
+
}
|
18
|
+
|
19
|
+
def setup
|
20
|
+
super
|
21
|
+
self.class.classes = CLASSES
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_id
|
25
|
+
testing_with do
|
26
|
+
assert_equal @first.id, @first.ids if composite?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_id_to_s
|
31
|
+
testing_with do
|
32
|
+
assert_equal first_id_str, @first.id.to_s
|
33
|
+
assert_equal first_id_str, "#{@first.id}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_ids_to_s
|
38
|
+
testing_with do
|
39
|
+
to_test = @klass.find(:all)[0..1].map(&:id)
|
40
|
+
assert_equal '(1,1),(1,2)', @klass.ids_to_s(to_test) if @key_test == :dual
|
41
|
+
assert_equal '1,1;1,2', @klass.ids_to_s(to_test, ',', ';', '', '') if @key_test == :dual
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_primary_keys
|
46
|
+
testing_with do
|
47
|
+
if composite?
|
48
|
+
assert_not_nil @klass.primary_keys
|
49
|
+
assert_equal @primary_keys, @klass.primary_keys
|
50
|
+
assert_equal @klass.primary_keys, @klass.primary_key
|
51
|
+
else
|
52
|
+
assert_not_nil @klass.primary_key
|
53
|
+
assert_equal @primary_keys, [@klass.primary_key.to_sym]
|
54
|
+
end
|
55
|
+
assert_equal @primary_keys.join(','), @klass.primary_key.to_s
|
56
|
+
# Need a :primary_keys should be Array with to_s overridden
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/test/miscellaneous_test.rb
CHANGED
@@ -3,6 +3,23 @@ require 'fixtures/reference_type'
|
|
3
3
|
require 'fixtures/reference_code'
|
4
4
|
|
5
5
|
class MiscellaneousTest < Test::Unit::TestCase
|
6
|
+
fixtures :reference_types, :reference_codes
|
7
|
+
|
8
|
+
CLASSES = {
|
9
|
+
:single => {
|
10
|
+
:class => ReferenceType,
|
11
|
+
:primary_keys => [:reference_type_id],
|
12
|
+
},
|
13
|
+
:dual => {
|
14
|
+
:class => ReferenceCode,
|
15
|
+
:primary_keys => [:reference_type_id, :reference_code],
|
16
|
+
},
|
17
|
+
}
|
18
|
+
|
19
|
+
def setup
|
20
|
+
super
|
21
|
+
self.class.classes = CLASSES
|
22
|
+
end
|
6
23
|
|
7
24
|
def test_composite_class
|
8
25
|
testing_with do
|
@@ -15,19 +32,4 @@ class MiscellaneousTest < Test::Unit::TestCase
|
|
15
32
|
assert_equal composite?, @first.composite?
|
16
33
|
end
|
17
34
|
end
|
18
|
-
|
19
|
-
def test_primary_keys
|
20
|
-
testing_with do
|
21
|
-
if composite?
|
22
|
-
assert_not_nil @klass.primary_keys
|
23
|
-
assert_equal @primary_keys, @klass.primary_keys
|
24
|
-
assert_equal @klass.primary_keys, @klass.primary_key
|
25
|
-
else
|
26
|
-
assert_not_nil @klass.primary_key
|
27
|
-
assert_equal @primary_keys, [@klass.primary_key.to_sym]
|
28
|
-
end
|
29
|
-
assert_equal @primary_keys.join(','), @klass.primary_key.to_s
|
30
|
-
# Need a :primary_keys should be Array with to_s overridden
|
31
|
-
end
|
32
|
-
end
|
33
35
|
end
|
data/test/pagination_test.rb
CHANGED
@@ -4,27 +4,32 @@ require 'fixtures/reference_code'
|
|
4
4
|
require 'action_controller/pagination'
|
5
5
|
|
6
6
|
class PaginationTest < Test::Unit::TestCase
|
7
|
+
fixtures :reference_types, :reference_codes
|
7
8
|
include ActionController::Pagination
|
8
9
|
DEFAULT_PAGE_SIZE = 2
|
9
|
-
|
10
|
-
|
10
|
+
|
11
|
+
CLASSES = {
|
11
12
|
:single => {
|
12
13
|
:class => ReferenceType,
|
13
14
|
:primary_keys => [:reference_type_id],
|
15
|
+
:table => :reference_types,
|
14
16
|
},
|
15
17
|
:dual => {
|
16
18
|
:class => ReferenceCode,
|
17
19
|
:primary_keys => [:reference_type_id, :reference_code],
|
18
|
-
|
20
|
+
:table => :reference_codes,
|
21
|
+
},
|
19
22
|
}
|
20
23
|
|
21
24
|
def setup
|
25
|
+
super
|
26
|
+
self.class.classes = CLASSES
|
22
27
|
@params = {}
|
23
28
|
end
|
24
29
|
|
25
30
|
def test_paginate_all
|
26
31
|
testing_with do
|
27
|
-
@object_pages, @objects = paginate :
|
32
|
+
@object_pages, @objects = paginate @klass_info[:table], :per_page => DEFAULT_PAGE_SIZE
|
28
33
|
assert_equal 2, @objects.length, "Each page should have #{DEFAULT_PAGE_SIZE} items"
|
29
34
|
end
|
30
35
|
end
|
data/test/update_test.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
require 'fixtures/reference_type'
|
3
|
+
require 'fixtures/reference_code'
|
4
|
+
|
5
|
+
class UpdateTest < Test::Unit::TestCase
|
6
|
+
fixtures :reference_types, :reference_codes
|
7
|
+
|
8
|
+
CLASSES = {
|
9
|
+
:single => {
|
10
|
+
:class => ReferenceType,
|
11
|
+
:primary_keys => [:reference_type_id],
|
12
|
+
:update => { :description => 'RT Desc' },
|
13
|
+
},
|
14
|
+
:dual => {
|
15
|
+
:class => ReferenceCode,
|
16
|
+
:primary_keys => [:reference_type_id, :reference_code],
|
17
|
+
:update => { :description => 'RT Desc' },
|
18
|
+
},
|
19
|
+
}
|
20
|
+
|
21
|
+
def setup
|
22
|
+
super
|
23
|
+
self.class.classes = CLASSES
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_setup
|
27
|
+
testing_with do
|
28
|
+
assert_not_nil @klass_info[:update]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_update_attributes
|
33
|
+
testing_with do
|
34
|
+
assert @first.update_attributes(@klass_info[:update])
|
35
|
+
assert @first.reload
|
36
|
+
@klass_info[:update].each_pair do |attr_name, new_value|
|
37
|
+
assert_equal new_value, @first[attr_name], "Attribute #{attr_name} is incorrect"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
metadata
CHANGED
@@ -3,14 +3,14 @@ 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.1
|
7
|
-
date: 2006-07-
|
6
|
+
version: 0.3.1
|
7
|
+
date: 2006-07-23 00:00:00 +02:00
|
8
8
|
summary: Support for composite primary keys in ActiveRecords
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
11
|
email: drnicwilliams@gmail.com
|
12
|
-
homepage: http://
|
13
|
-
rubyforge_project:
|
12
|
+
homepage: http://compositekeys.rubyforge.org
|
13
|
+
rubyforge_project: compositekeys
|
14
14
|
description: ActiveRecords only support a single primary key, preventing their use on legacy databases where tables have primary keys over 2+ columns. This solution allows an ActiveRecord to be extended to support multiple keys using the class method set_primary_keys.
|
15
15
|
autorequire: composite_primary_keys
|
16
16
|
default_executable:
|
@@ -34,18 +34,23 @@ files:
|
|
34
34
|
- CHANGELOG
|
35
35
|
- lib/composite_primary_keys
|
36
36
|
- lib/composite_primary_keys.rb
|
37
|
+
- lib/composite_primary_keys/fixtures.rb
|
38
|
+
- lib/composite_primary_keys/composite_arrays.rb
|
37
39
|
- lib/composite_primary_keys/version.rb
|
38
40
|
- lib/composite_primary_keys/base.rb
|
39
|
-
- lib/composite_primary_keys/fixtures.rb
|
40
|
-
- lib/composite_primary_keys/primary_keys.rb
|
41
41
|
- test/connections
|
42
|
-
- test/abstract_unit.rb
|
43
|
-
- test/dummy_test.rb
|
44
42
|
- test/fixtures
|
43
|
+
- test/composite_arrays_test.rb
|
44
|
+
- test/hash_tricks.rb
|
45
|
+
- test/delete_test.rb
|
46
|
+
- test/ids_test.rb
|
45
47
|
- test/find_test.rb
|
46
|
-
- test/
|
48
|
+
- test/update_test.rb
|
49
|
+
- test/abstract_unit.rb
|
47
50
|
- test/miscellaneous_test.rb
|
48
|
-
- test/
|
51
|
+
- test/pagination_test.rb
|
52
|
+
- test/dummy_test.rb
|
53
|
+
- test/clone_test.rb
|
49
54
|
- test/connections/native_mysql
|
50
55
|
- test/connections/native_mysql/connection.rb
|
51
56
|
- test/fixtures/reference_type.rb
|
data/test/primary_keys_test.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'abstract_unit'
|
2
|
-
require 'fixtures/reference_type'
|
3
|
-
require 'fixtures/reference_code'
|
4
|
-
|
5
|
-
class PrimaryKeyTest < Test::Unit::TestCase
|
6
|
-
|
7
|
-
def test_new
|
8
|
-
keys = CompositePrimaryKeys::PrimaryKeys.new
|
9
|
-
assert_not_nil keys
|
10
|
-
assert_equal '', keys.to_s
|
11
|
-
assert_equal '', "#{keys}"
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_initialize
|
15
|
-
keys = CompositePrimaryKeys::PrimaryKeys.new([1,2,3])
|
16
|
-
assert_not_nil keys
|
17
|
-
assert_equal '1,2,3', keys.to_s
|
18
|
-
assert_equal '1,2,3', "#{keys}"
|
19
|
-
end
|
20
|
-
end
|