composite_primary_keys 0.1.4 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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 = CompositePrimayKeys::VERSION::STRING + PKG_BUILD
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 => [:drop_mysql_databases] do
42
+ task :build_mysql_databases do
42
43
  puts File.join(SCHEMA_PATH, 'mysql.sql')
43
- %x( mysqladmin -u root create activerecord_unittest )
44
- #%x( mysqladmin -u root create activerecord_unittest2 )
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 activerecord_unittest )
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 activerecord_unittest )
61
- %x( createdb activerecord_unittest2 )
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 activerecord_unittest )
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://composite_primary_keys.rubyforge.org"
121
- s.rubyforge_project = "composite_primary_keys"
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`
@@ -34,6 +34,7 @@ unless defined?(ActiveRecord)
34
34
  end
35
35
  end
36
36
 
37
+ require 'composite_primary_keys/composite_arrays'
37
38
  require 'composite_primary_keys/base'
38
39
 
39
40
  ActiveRecord::Base.class_eval do
@@ -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 = CompositePrimaryKeys::PrimaryKeys.new(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
- attr_names.map {|attr_name| read_attribute(attr_name)}
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
- # TODO
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
- # TODO
63
- quote(id, column_for_attribute(self.class.primary_key))
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]], ',', ';', '', '') -> "1,2;7,3"
125
- def ids_to_s(ids, id_sep = CompositePrimaryKeys::ID_SEP, list_sep = ',', left_bracket = '(', right_bracket = ')')
126
- "#{left_bracket}#{ids.map{|id| sanitize(id)}.join('#{id_sep}')}#{right_bracket}"
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.first.is_a?(Array) ? ids.each { |id_set| destroy(id_set) } : find(ids).destroy
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)
@@ -1,8 +1,8 @@
1
- module CompositePrimayKeys
1
+ module CompositePrimaryKeys
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 1
5
- TINY = 4
4
+ MINOR = 3
5
+ TINY = 1
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -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
- @klass, @primary_keys = classes[@key_test][:class], classes[@key_test][:primary_keys]
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
@@ -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
@@ -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
- assert true
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
- @@classes = {
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
@@ -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
@@ -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
@@ -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
- @@classes = {
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 :reference_codes, :per_page => DEFAULT_PAGE_SIZE
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
@@ -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.4
7
- date: 2006-07-22 00:00:00 +02:00
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://composite_primary_keys.rubyforge.org
13
- rubyforge_project: composite_primary_keys
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/pagination_test.rb
48
+ - test/update_test.rb
49
+ - test/abstract_unit.rb
47
50
  - test/miscellaneous_test.rb
48
- - test/primary_keys_test.rb
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
@@ -1,10 +0,0 @@
1
- module CompositePrimaryKeys
2
- ID_SEP = ','
3
-
4
- class PrimaryKeys < Array
5
-
6
- def to_s
7
- join(ID_SEP)
8
- end
9
- end
10
- end
@@ -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