composite_primary_keys 3.1.6 → 3.1.7

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,11 @@
1
+ == 3.1.7 2011-05-19
2
+ * Support regular AR models having one or many composite models (Jacques Fuentes)
3
+ * Minor test cleanup
4
+ * Make version requirements more explicit
5
+ * Remove Arel extensions used for calculations
6
+ * Fix test that included wrong error constant
7
+
8
+
1
9
  == 3.1.6 2011-04-03
2
10
  * Updated belongs_to association to be a bit more flexible with non-CPK
3
11
  base models (Jacques Fuentes)
@@ -5,12 +13,14 @@
5
13
  * Fix write issue when one of they keys in a composite key is
6
14
  called id (Tom Hughes)
7
15
 
16
+
8
17
  == 3.1.5 2011-03-24
9
18
  * Fix simple calculation methods
10
19
  * Fix instantiation of cpk records via associations.
11
20
  * Fix Relation#delete
12
21
  * Fix Relation#destroy
13
22
 
23
+
14
24
  == 3.1.4 2011-03-06
15
25
  * Support ActiveRecord 3.0.5 (interpolate_sql was removed and
16
26
  replaced by interpolate_and_sanitize_sql)
@@ -25,12 +25,9 @@ $:.unshift(File.dirname(__FILE__)) unless
25
25
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
26
26
 
27
27
  unless defined?(ActiveRecord)
28
- begin
29
- require 'active_record'
30
- rescue LoadError
31
- require 'rubygems'
32
- gem 'active_record'
33
- end
28
+ gem 'arel', '~> 2.0.0'
29
+ gem 'activerecord', '>= 3.0.5', '~> 3.0.0'
30
+ require 'active_record'
34
31
  end
35
32
 
36
33
  require 'active_record/associations.rb'
@@ -49,7 +46,6 @@ require 'active_record/relation/query_methods'
49
46
  require 'active_record/attribute_methods/primary_key'
50
47
  require 'active_record/fixtures'
51
48
 
52
- require 'composite_primary_keys/arel_extensions'
53
49
  require 'composite_primary_keys/composite_arrays'
54
50
  require 'composite_primary_keys/associations'
55
51
  require 'composite_primary_keys/associations/association_proxy'
@@ -30,4 +30,4 @@ module ActiveRecord
30
30
  end
31
31
  end
32
32
  end
33
- end
33
+ end
@@ -22,6 +22,14 @@ module ActiveRecord
22
22
  construct_counter_sql
23
23
  end
24
24
 
25
+ def owner_quoted_id
26
+ if (keys = @reflection.options[:primary_key])
27
+ keys.is_a?(Array) ? keys.collect {|k| quote_value(@owner.send(k)) } : quote_value(@owner.send(keys))
28
+ else
29
+ @owner.quoted_id
30
+ end
31
+ end
32
+
25
33
  def delete_records(records)
26
34
  case @reflection.options[:dependent]
27
35
  when :destroy
@@ -70,4 +78,4 @@ module ActiveRecord
70
78
  end
71
79
  end
72
80
  end
73
- end
81
+ end
@@ -14,6 +14,14 @@ module ActiveRecord
14
14
  end
15
15
  @finder_sql << " AND (#{conditions})" if conditions
16
16
  end
17
+
18
+ def owner_quoted_id
19
+ if (keys = @reflection.options[:primary_key])
20
+ keys.is_a?(Array) ? keys.collect {|k| @owner.class.quote_value(@owner.send(k)) } : @owner.class.quote_value(@owner.send(keys))
21
+ else
22
+ @owner.quoted_id
23
+ end
24
+ end
17
25
  end
18
26
  end
19
- end
27
+ end
@@ -16,12 +16,16 @@ module ActiveRecord
16
16
  self.arel.visitor.accept(attribute)
17
17
  end.join(', ')
18
18
 
19
- relation = self.clone
20
- relation.select_values = ["DISTINCT #{projection}"]
19
+ # relation = self.clone
20
+ # relation.select_values = ["DISTINCT #{projection}"]
21
21
 
22
- table = Arel::Table.new('dummy').project('count(*)')
23
- relation = table.from(relation.arel, "foobar")
24
- type_cast_calculated_value(@klass.connection.select_value(relation.to_sql), column_for(column_name), operation)
22
+ manager = Arel::SelectManager.new(arel_engine)
23
+ manager.project("DISTINCT #{projection}")
24
+ manager.from(arel_table)
25
+
26
+ query = Arel::Table.new('dummy').project('count(*)')
27
+ query = query.from("(#{manager.to_sql}) AS subquery")
28
+ type_cast_calculated_value(@klass.connection.select_value(query.to_sql), column_for(column_name), operation)
25
29
  end
26
30
  end
27
31
  end
@@ -2,7 +2,7 @@ module CompositePrimaryKeys
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 3
4
4
  MINOR = 1
5
- TINY = 6
5
+ TINY = 7
6
6
  STRING = [MAJOR, MINOR, TINY].join('.')
7
7
  end
8
8
  end
@@ -7,16 +7,15 @@ require 'pp'
7
7
  require 'test/unit'
8
8
  require 'hash_tricks'
9
9
  require 'rubygems'
10
- require 'active_record'
11
- require 'active_record/fixtures'
12
- require File.join(PROJECT_ROOT, 'test', 'connections', 'connection_spec')
13
- require File.join(PROJECT_ROOT, "test", "connections", "native_#{adapter}", "connection")
14
-
15
10
 
16
11
  # To make debugging easier, test within this source tree versus an installed gem
17
12
  #require 'composite_primary_keys'
18
13
  require File.join(PROJECT_ROOT, "lib", "composite_primary_keys")
19
14
 
15
+ require 'active_record/fixtures'
16
+ require File.join(PROJECT_ROOT, 'test', 'connections', 'connection_spec')
17
+ require File.join(PROJECT_ROOT, "test", "connections", "native_#{adapter}", "connection")
18
+
20
19
  # Tell ActiveRecord where to find models
21
20
  ActiveSupport::Dependencies.autoload_paths << File.join(PROJECT_ROOT, 'test', 'fixtures')
22
21
 
@@ -7,7 +7,7 @@ def connection_string
7
7
  options['u'] = SPEC['username'] if SPEC['username']
8
8
  options['p'] = SPEC['password'] if SPEC['password']
9
9
  options['S'] = SPEC['sock'] if SPEC['sock']
10
- options.map { |key, value| "-#{key} #{value}" }.join(" ")
10
+ options.map { |key, value| "-#{key}#{value}" }.join(" ")
11
11
  end
12
12
 
13
13
  # Adapter config setup in locals/database_connections.rb
@@ -1,5 +1,4 @@
1
1
  class Department < ActiveRecord::Base
2
- # set_primary_keys *keys - turns on composite key functionality
3
2
  set_primary_keys :department_id, :location_id
4
3
  has_many :employees, :foreign_key => [:department_id, :location_id]
5
4
  end
@@ -1,3 +1,3 @@
1
1
  class Dorm < ActiveRecord::Base
2
- has_many :rooms, :include => :room_attributes
2
+ has_many :rooms, :include => :room_attributes, :primary_key => [:id]
3
3
  end
@@ -1,2 +1,2 @@
1
- jacksons_dorm:
1
+ branner:
2
2
  id: 1
@@ -1,7 +1,7 @@
1
1
  class Product < ActiveRecord::Base
2
2
  set_primary_keys :id # redundant
3
3
  has_many :product_tariffs, :foreign_key => :product_id, :dependent => :delete_all
4
- has_one :product_tariff, :foreign_key => :product_id
5
-
4
+ # Yeah, this is fake, it uses for testing
5
+ has_one :product_tariff, :foreign_key => :product_id
6
6
  has_many :tariffs, :through => :product_tariffs, :foreign_key => [:tariff_id, :tariff_start_date]
7
7
  end
@@ -2,10 +2,12 @@ first_flat:
2
2
  product_id: 1
3
3
  tariff_id: 1
4
4
  tariff_start_date: <%= Date.today.to_s(:db) %>
5
+
5
6
  first_free:
6
7
  product_id: 1
7
8
  tariff_id: 2
8
9
  tariff_start_date: <%= Date.today.to_s(:db) %>
10
+
9
11
  second_free:
10
12
  product_id: 2
11
13
  tariff_id: 2
@@ -1,6 +1,7 @@
1
1
  first_product:
2
2
  id: 1
3
3
  name: Product One
4
+
4
5
  second_product:
5
6
  id: 2
6
7
  name: Product Two
@@ -1,6 +1,7 @@
1
1
  class Room < ActiveRecord::Base
2
2
  set_primary_keys :dorm_id, :room_id
3
3
  belongs_to :dorm
4
+ has_many :room_assignments, :foreign_key => [:dorm_id, :room_id]
4
5
  has_many :room_attribute_assignments, :foreign_key => [:dorm_id, :room_id]
5
6
  has_many :room_attributes, :through => :room_attribute_assignments
6
7
 
@@ -1,6 +1,7 @@
1
1
  class RoomAssignment < ActiveRecord::Base
2
+ set_primary_keys :student_id, :dorm_id, :room_id
2
3
  belongs_to :student
3
- belongs_to :room, :foreign_key => [:dorm_id, :room_id]
4
+ belongs_to :room, :foreign_key => [:dorm_id, :room_id], :primary_key => [:dorm_id, :room_id]
4
5
 
5
6
  before_destroy do |record|
6
7
  puts record
@@ -1,4 +1,9 @@
1
1
  jacksons_room:
2
2
  student_id: 1
3
3
  dorm_id: 1
4
+ room_id: 1
5
+
6
+ bobs_room:
7
+ student_id: 2
8
+ dorm_id: 1
4
9
  room_id: 1
@@ -1,3 +1,7 @@
1
- jacksons_room:
2
- dorm_id: 1
3
- room_id: 1
1
+ branner_room_1:
2
+ dorm_id: 1
3
+ room_id: 1
4
+
5
+ branner_room_2:
6
+ dorm_id: 1
7
+ room_id: 2
@@ -1,2 +1,5 @@
1
1
  jackson:
2
- id: 1
2
+ id: 1
3
+
4
+ bob:
5
+ id: 2
@@ -5,26 +5,6 @@ class TestAssociations < ActiveSupport::TestCase
5
5
  :dorms, :rooms, :room_attributes, :room_attribute_assignments, :students, :room_assignments, :users, :readings,
6
6
  :memberships
7
7
 
8
- def test_has_many_through_with_conditions_when_through_association_is_not_composite
9
- user = User.find(:first)
10
- assert_equal 1, user.articles.find(:all, :conditions => ["articles.name = ?", "Article One"]).size
11
- end
12
-
13
- def test_has_many_through_with_conditions_when_through_association_is_composite
14
- room = Room.find(:first)
15
- assert_equal 0, room.room_attributes.find(:all, :conditions => ["room_attributes.name != ?", "keg"]).size
16
- end
17
-
18
- def test_has_many_through_on_custom_finder_when_through_association_is_composite_finder_when_through_association_is_not_composite
19
- user = User.find(:first)
20
- assert_equal 1, user.find_custom_articles.size
21
- end
22
-
23
- def test_has_many_through_on_custom_finder_when_through_association_is_composite
24
- room = Room.find(:first)
25
- assert_equal 0, room.find_custom_room_attributes.size
26
- end
27
-
28
8
  def test_count
29
9
  assert_equal(2, Product.count(:include => :product_tariffs))
30
10
  assert_equal(3, Tariff.count(:include => :product_tariffs))
@@ -141,9 +121,9 @@ class TestAssociations < ActiveSupport::TestCase
141
121
 
142
122
  def test_has_many_through_when_through_association_is_composite
143
123
  dorm = Dorm.find(:first)
144
- assert_equal 1, dorm.rooms.length
145
- assert_equal 1, dorm.rooms.first.room_attributes.length
146
- assert_equal 'keg', dorm.rooms.first.room_attributes.first.name
124
+ assert_equal(2, dorm.rooms.length)
125
+ assert_equal(1, dorm.rooms.first.room_attributes.length)
126
+ assert_equal('keg', dorm.rooms.first.room_attributes.first.name)
147
127
  end
148
128
 
149
129
  def test_associations_with_conditions
@@ -160,6 +140,18 @@ class TestAssociations < ActiveSupport::TestCase
160
140
  assert_equal 1, @suburb.first_streets.size
161
141
  end
162
142
 
143
+ def test_composite_has_many_composites
144
+ room = rooms(:branner_room_1)
145
+ assert_equal(2, room.room_assignments.length)
146
+ assert_equal(room_assignments(:jacksons_room), room.room_assignments[0])
147
+ assert_equal(room_assignments(:bobs_room), room.room_assignments[1])
148
+ end
149
+
150
+ def test_composite_belongs_to_composite
151
+ room_assignment = room_assignments(:jacksons_room)
152
+ assert_equal(rooms(:branner_room_1), room_assignment.room)
153
+ end
154
+
163
155
  def test_has_and_belongs_to_many
164
156
  @restaurant = Restaurant.find([1,1])
165
157
  assert_equal 2, @restaurant.suburbs.size
@@ -168,16 +160,29 @@ class TestAssociations < ActiveSupport::TestCase
168
160
  assert_equal 2, @restaurant.suburbs.size
169
161
  end
170
162
 
171
- def test_has_many_with_primary_key
163
+ def test_has_one_with_primary_key
172
164
  @membership = Membership.find([1, 1])
165
+ assert_equal 2, @membership.reading.id
166
+ end
173
167
 
174
- assert_equal 2, @membership.readings.size
168
+ def test_has_one_with_composite
169
+ # In this case a regular model has_one composite model
170
+ product = products(:first_product)
171
+ assert_not_nil(product.product_tariff)
175
172
  end
176
173
 
177
- def test_has_one_with_primary_key
174
+ def test_has_many_with_primary_key
178
175
  @membership = Membership.find([1, 1])
179
176
 
180
- assert_equal 2, @membership.reading.id
177
+ assert_equal 2, @membership.readings.size
178
+ end
179
+
180
+ def test_has_many_with_composite_key
181
+ # In this case a regular model has_many composite models
182
+ dorm = dorms(:branner)
183
+ assert_equal(2, dorm.rooms.length)
184
+ assert_equal(1, dorm.rooms[0].room_id)
185
+ assert_equal(2, dorm.rooms[1].room_id)
181
186
  end
182
187
 
183
188
  def test_joins_has_many_with_primary_key
@@ -192,6 +197,26 @@ class TestAssociations < ActiveSupport::TestCase
192
197
  assert_equal [1, 1], @membership.id
193
198
  end
194
199
 
200
+ def test_has_many_through_with_conditions_when_through_association_is_not_composite
201
+ user = User.find(:first)
202
+ assert_equal 1, user.articles.find(:all, :conditions => ["articles.name = ?", "Article One"]).size
203
+ end
204
+
205
+ def test_has_many_through_with_conditions_when_through_association_is_composite
206
+ room = Room.find(:first)
207
+ assert_equal 0, room.room_attributes.find(:all, :conditions => ["room_attributes.name != ?", "keg"]).size
208
+ end
209
+
210
+ def test_has_many_through_on_custom_finder_when_through_association_is_composite_finder_when_through_association_is_not_composite
211
+ user = User.find(:first)
212
+ assert_equal 1, user.find_custom_articles.size
213
+ end
214
+
215
+ def test_has_many_through_on_custom_finder_when_through_association_is_composite
216
+ room = Room.find(:first)
217
+ assert_equal 0, room.find_custom_room_attributes.size
218
+ end
219
+
195
220
  def test_has_many_with_primary_key_with_associations
196
221
  # Trigger Active Records find_with_associations method
197
222
  memberships = Membership.find(:all, :include => :statuses,
data/test/test_create.rb CHANGED
@@ -38,7 +38,7 @@ class TestCreate < ActiveSupport::TestCase
38
38
  begin
39
39
  @obj = @klass.create(@klass_info[:create].block(@klass.primary_key))
40
40
  @successful = !composite?
41
- rescue CompositePrimaryKeys::ActiveRecord::CompositeKeyError
41
+ rescue ActiveRecord::CompositeKeyError
42
42
  @successful = false
43
43
  rescue
44
44
  flunk "Incorrect exception raised: #{$!}, #{$!.class}"
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: composite_primary_keys
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 13
5
5
  prerelease:
6
6
  segments:
7
7
  - 3
8
8
  - 1
9
- - 6
10
- version: 3.1.6
9
+ - 7
10
+ version: 3.1.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Dr Nic Williams
@@ -16,13 +16,28 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2011-04-03 00:00:00 -06:00
20
- default_executable:
19
+ date: 2011-05-19 00:00:00 Z
21
20
  dependencies:
22
21
  - !ruby/object:Gem::Dependency
23
- name: activerecord
22
+ name: arel
24
23
  prerelease: false
25
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 15
30
+ segments:
31
+ - 2
32
+ - 0
33
+ - 0
34
+ version: 2.0.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: activerecord
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
26
41
  none: false
27
42
  requirements:
28
43
  - - ">="
@@ -33,12 +48,20 @@ dependencies:
33
48
  - 0
34
49
  - 5
35
50
  version: 3.0.5
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ hash: 7
54
+ segments:
55
+ - 3
56
+ - 0
57
+ - 0
58
+ version: 3.0.0
36
59
  type: :runtime
37
- version_requirements: *id001
60
+ version_requirements: *id002
38
61
  - !ruby/object:Gem::Dependency
39
62
  name: rspec
40
63
  prerelease: false
41
- requirement: &id002 !ruby/object:Gem::Requirement
64
+ requirement: &id003 !ruby/object:Gem::Requirement
42
65
  none: false
43
66
  requirements:
44
67
  - - ">="
@@ -48,7 +71,7 @@ dependencies:
48
71
  - 0
49
72
  version: "0"
50
73
  type: :development
51
- version_requirements: *id002
74
+ version_requirements: *id003
52
75
  description: Composite key support for ActiveRecord 3
53
76
  email:
54
77
  - drnicwilliams@gmail.com
@@ -66,7 +89,6 @@ files:
66
89
  - init.rb
67
90
  - install.rb
68
91
  - loader.rb
69
- - lib/composite_primary_keys/arel_extensions.rb
70
92
  - lib/composite_primary_keys/associations/association_proxy.rb
71
93
  - lib/composite_primary_keys/associations/has_and_belongs_to_many_association.rb
72
94
  - lib/composite_primary_keys/associations/has_many_association.rb
@@ -186,7 +208,6 @@ files:
186
208
  - test/plugins/pagination_helper.rb
187
209
  - test/README_tests.txt
188
210
  - test/setup.rb
189
- - test/test_arel.rb
190
211
  - test/test_associations.rb
191
212
  - test/test_attributes.rb
192
213
  - test/test_attribute_methods.rb
@@ -206,7 +227,6 @@ files:
206
227
  - test/test_tutorial_example.rb
207
228
  - test/test_update.rb
208
229
  - test/test_validations.rb
209
- has_rdoc: true
210
230
  homepage: http://github.com/cfis/composite_primary_keys
211
231
  licenses: []
212
232
 
@@ -238,7 +258,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
238
258
  requirements: []
239
259
 
240
260
  rubyforge_project: compositekeys
241
- rubygems_version: 1.6.2
261
+ rubygems_version: 1.7.2
242
262
  signing_key:
243
263
  specification_version: 3
244
264
  summary: Composite key support for ActiveRecord
@@ -249,7 +269,6 @@ test_files:
249
269
  - test/hash_tricks.rb
250
270
  - test/README_tests.txt
251
271
  - test/setup.rb
252
- - test/test_arel.rb
253
272
  - test/test_associations.rb
254
273
  - test/test_attributes.rb
255
274
  - test/test_attribute_methods.rb
@@ -1,47 +0,0 @@
1
- module Arel
2
- module Nodes
3
- class SubSelect < Node
4
- attr_accessor :select, :as
5
-
6
- def initialize(select, as = 'subquery')
7
- @select = select
8
- @as = as
9
- end
10
- end
11
- end
12
-
13
- module Visitors
14
- class ToSql
15
- def visit_Arel_Nodes_SubSelect o
16
- "(#{visit(o.select)}) AS #{o.as}"
17
- end
18
- end
19
- end
20
-
21
- class SelectManager
22
- def from table, as = nil
23
- table = case table
24
- when Arel::SelectManager
25
- Nodes::SubSelect.new(table.ast, as)
26
- when String
27
- Nodes::SqlLiteral.new(table)
28
- else
29
- table
30
- end
31
-
32
- # FIXME: this is a hack to support
33
- # test_with_two_tables_in_from_without_getting_double_quoted
34
- # from the AR tests.
35
- if @ctx.froms
36
- source = @ctx.froms
37
-
38
- if Nodes::SqlLiteral === table && Nodes::Join === source
39
- source.left = table
40
- table = source
41
- end
42
- end
43
- @ctx.froms = table
44
- self
45
- end
46
- end
47
- end
data/test/test_arel.rb DELETED
@@ -1,79 +0,0 @@
1
- require 'abstract_unit'
2
-
3
-
4
- module Arel
5
- module Nodes
6
- class SubSelect < Node
7
- attr_accessor :select, :as
8
-
9
- def initialize(select, as = 'subquery')
10
- @select = select
11
- @as = as
12
- end
13
- end
14
- end
15
-
16
- module Visitors
17
- class ToSql
18
- def visit_Arel_Nodes_SubSelect o
19
- "(#{visit(o.select)}) AS #{o.as}"
20
- end
21
- end
22
- end
23
-
24
- class SelectManager
25
- def from table, as = nil
26
- table = case table
27
- when Arel::SelectManager
28
- Nodes::SubSelect.new(table.ast, as)
29
- when String
30
- Nodes::SqlLiteral.new(table)
31
- else
32
- table
33
- end
34
-
35
- # FIXME: this is a hack to support
36
- # test_with_two_tables_in_from_without_getting_double_quoted
37
- # from the AR tests.
38
- if @ctx.froms
39
- source = @ctx.froms
40
-
41
- if Nodes::SqlLiteral === table && Nodes::Join === source
42
- source.left = table
43
- table = source
44
- end
45
- end
46
- @ctx.froms = table
47
- self
48
- end
49
- end
50
- end
51
-
52
-
53
-
54
- #class TestArel < Test::Unit::TestCase
55
- # def test_engine
56
- # assert_not_nil(Arel::Table)
57
- # assert_not_nil(Arel::Table.engine)
58
- # end
59
- #end
60
-
61
- visitor = Arel::Visitors::ToSql.new(Arel::Table.engine)
62
-
63
- tariffs = Arel::Table.new(:tariffs)
64
- product_tariffs = Arel::Table.new(:product_tariffs)
65
- subquery = tariffs.join(product_tariffs).on(tariffs[:tariff_id].eq(product_tariffs[:tariff_id]).and(tariffs[:start_date].eq(product_tariffs[:tariff_start_date])))
66
-
67
- projection = ['tariff_id', 'start_date'].map do |key|
68
- visitor.accept(tariffs[key])
69
- end.join(', ')
70
-
71
- subquery.project("DISTINCT #{projection}")
72
-
73
- table = Arel::Table.new('test').project('count(*)')
74
- query = table.from(subquery, "foobar")
75
-
76
- puts "***********"
77
- puts query.to_sql
78
- a = query.to_a
79
- puts a