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 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