composite_primary_keys 3.1.4 → 3.1.5
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/History.txt +8 -1
- data/lib/composite_primary_keys.rb +1 -0
- data/lib/composite_primary_keys/arel_extensions.rb +47 -0
- data/lib/composite_primary_keys/associations.rb +17 -0
- data/lib/composite_primary_keys/calculations.rb +27 -42
- data/lib/composite_primary_keys/finder_methods.rb +6 -7
- data/lib/composite_primary_keys/reflection.rb +1 -1
- data/lib/composite_primary_keys/relation.rb +29 -15
- data/lib/composite_primary_keys/version.rb +1 -1
- data/test/test_arel.rb +79 -0
- data/test/test_associations.rb +5 -1
- metadata +8 -5
data/History.txt
CHANGED
@@ -1,7 +1,14 @@
|
|
1
|
-
== 3.1.
|
1
|
+
== 3.1.5 2011-03-24
|
2
|
+
* Fix simple calculation methods
|
3
|
+
* Fix instantiation of cpk records via associations.
|
4
|
+
* Fix Relation#delete_all
|
5
|
+
* Fix Relation#destroy
|
6
|
+
|
7
|
+
== 3.1.4 2011-03-06
|
2
8
|
* Support ActiveRecord 3.0.5 (interpolate_sql was removed and
|
3
9
|
replaced by interpolate_and_sanitize_sql)
|
4
10
|
* Fix persistence methods to support destroy callbacks
|
11
|
+
* Support rake 0.9.0 beta
|
5
12
|
|
6
13
|
|
7
14
|
== 3.1.2 2011-02-26
|
@@ -49,6 +49,7 @@ require 'active_record/relation/query_methods'
|
|
49
49
|
require 'active_record/attribute_methods/primary_key'
|
50
50
|
require 'active_record/fixtures'
|
51
51
|
|
52
|
+
require 'composite_primary_keys/arel_extensions'
|
52
53
|
require 'composite_primary_keys/composite_arrays'
|
53
54
|
require 'composite_primary_keys/associations'
|
54
55
|
require 'composite_primary_keys/associations/association_proxy'
|
@@ -0,0 +1,47 @@
|
|
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
|
@@ -3,6 +3,23 @@ module ActiveRecord
|
|
3
3
|
module ClassMethods
|
4
4
|
class JoinDependency
|
5
5
|
class JoinBase
|
6
|
+
def aliased_primary_key
|
7
|
+
# CPK
|
8
|
+
# "#{aliased_prefix}_r0"
|
9
|
+
|
10
|
+
active_record.composite? ?
|
11
|
+
primary_key.inject([]) {|aliased_keys, key| aliased_keys << "#{ aliased_prefix }_r#{aliased_keys.length}"} :
|
12
|
+
"#{ aliased_prefix }_r0"
|
13
|
+
end
|
14
|
+
|
15
|
+
def record_id(row)
|
16
|
+
# CPK
|
17
|
+
# row[aliased_primary_key]
|
18
|
+
active_record.composite? ?
|
19
|
+
aliased_primary_key.map {|key| row[key]}.to_composite_keys :
|
20
|
+
row[aliased_primary_key]
|
21
|
+
end
|
22
|
+
|
6
23
|
def column_names_with_alias
|
7
24
|
unless defined?(@column_names_with_alias)
|
8
25
|
@column_names_with_alias = []
|
@@ -1,42 +1,27 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
#
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
#
|
29
|
-
# #select_value = ::Arel::Nodes::Count.new(columns, distinct)
|
30
|
-
# # relation.select_values = columns
|
31
|
-
# # puts @klass.connection.select_value(relation.to_sql)
|
32
|
-
##
|
33
|
-
# #type_cast_calculated_value(@klass.connection.select_value(relation.to_sql), column_for(column_name), operation)
|
34
|
-
# #relation.select_values = [count_node]
|
35
|
-
# #projection = "DISTINCT #{columns.join(',')}"
|
36
|
-
# #subquery = "(#{table.project(projection).to_sql}) AS subquery"
|
37
|
-
# #relation = Arel::Table.new(subquery).project(Arel::SqlLiteral.new('*').count)
|
38
|
-
# type_cast_calculated_value(@klass.connection.select_value(relation.to_sql),
|
39
|
-
# column_for(column_name.first), operation)
|
40
|
-
# end
|
41
|
-
# end
|
42
|
-
#end
|
1
|
+
module ActiveRecord
|
2
|
+
module Calculations
|
3
|
+
alias :execute_simple_calculation_ar :execute_simple_calculation
|
4
|
+
def execute_simple_calculation(operation, column_name, distinct)
|
5
|
+
# CPK
|
6
|
+
if column_name.kind_of?(Array)
|
7
|
+
execute_simple_calculation_cpk(operation, column_name, distinct)
|
8
|
+
else
|
9
|
+
execute_simple_calculation_ar(operation, column_name, distinct)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def execute_simple_calculation_cpk(operation, column_name, distinct)
|
14
|
+
projection = self.primary_keys.map do |key|
|
15
|
+
attribute = arel_table[key]
|
16
|
+
self.arel.visitor.accept(attribute)
|
17
|
+
end.join(', ')
|
18
|
+
|
19
|
+
relation = self.clone
|
20
|
+
relation.select_values = ["DISTINCT #{projection}"]
|
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)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -51,7 +51,7 @@ module CompositePrimaryKeys
|
|
51
51
|
# CPK
|
52
52
|
when CompositePrimaryKeys::CompositeKeys
|
53
53
|
relation = select(primary_keys).limit(1)
|
54
|
-
relation = relation.
|
54
|
+
relation = relation.where_cpk_id(id) if id
|
55
55
|
relation.first ? true : false
|
56
56
|
when Array
|
57
57
|
# CPK
|
@@ -63,12 +63,11 @@ module CompositePrimaryKeys
|
|
63
63
|
when Hash
|
64
64
|
where(id).exists?
|
65
65
|
else
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
66
|
+
# CPK
|
67
|
+
#relation = select(primary_key).limit(1)
|
68
|
+
#relation = relation.where(primary_key.eq(id)) if id
|
69
|
+
relation = select(primary_keys).limit(1)
|
70
|
+
relation = relation.where_cpk_id(id) if id
|
72
71
|
relation.first ? true : false
|
73
72
|
end
|
74
73
|
end
|
@@ -2,35 +2,49 @@ module CompositePrimaryKeys
|
|
2
2
|
module ActiveRecord
|
3
3
|
module Relation
|
4
4
|
module InstanceMethods
|
5
|
-
def
|
6
|
-
|
5
|
+
def where_cpk_id(id)
|
6
|
+
relation = clone
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
predicates = self.primary_keys.zip(Array(id)).map do |key, value|
|
9
|
+
table[key].eq(value)
|
10
10
|
end
|
11
|
-
|
12
|
-
|
13
|
-
self.primary_keys.zip(composite_id).each do |key, value|
|
14
|
-
eq = table[key].eq(value)
|
15
|
-
predicate = predicate ? predicate.and(eq) : eq
|
16
|
-
end
|
17
|
-
end
|
18
|
-
predicate
|
11
|
+
relation.where_values += predicates
|
12
|
+
relation
|
19
13
|
end
|
20
14
|
|
21
15
|
def delete(id_or_array)
|
22
16
|
# CPK
|
23
17
|
# where(@klass.primary_key => id_or_array).delete_all
|
24
|
-
|
18
|
+
|
19
|
+
id_or_array = if id_or_array.kind_of?(CompositePrimaryKeys::CompositeKeys)
|
20
|
+
[id_or_array]
|
21
|
+
else
|
22
|
+
Array(id_or_array)
|
23
|
+
end
|
24
|
+
|
25
|
+
id_or_array.each do |id|
|
26
|
+
where_cpk_id(id).delete_all
|
27
|
+
end
|
25
28
|
end
|
26
29
|
|
27
|
-
def destroy(
|
30
|
+
def destroy(id_or_array)
|
28
31
|
# CPK
|
29
32
|
#if id.is_a?(Array)
|
30
33
|
# id.map { |one_id| destroy(one_id) }
|
31
34
|
#else
|
32
|
-
|
35
|
+
# find(id).destroy
|
33
36
|
#end
|
37
|
+
id_or_array = if id_or_array.kind_of?(CompositePrimaryKeys::CompositeKeys)
|
38
|
+
[id_or_array]
|
39
|
+
else
|
40
|
+
Array(id_or_array)
|
41
|
+
end
|
42
|
+
|
43
|
+
id_or_array.each do |id|
|
44
|
+
where_cpk_id(id).each do |record|
|
45
|
+
record.destroy
|
46
|
+
end
|
47
|
+
end
|
34
48
|
end
|
35
49
|
end
|
36
50
|
end
|
data/test/test_arel.rb
ADDED
@@ -0,0 +1,79 @@
|
|
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
|
data/test/test_associations.rb
CHANGED
@@ -28,7 +28,11 @@ class TestAssociations < ActiveSupport::TestCase
|
|
28
28
|
def test_count
|
29
29
|
assert_equal(2, Product.count(:include => :product_tariffs))
|
30
30
|
assert_equal(3, Tariff.count(:include => :product_tariffs))
|
31
|
-
|
31
|
+
|
32
|
+
expected = {Date.today => 2,
|
33
|
+
Date.today.next => 1}
|
34
|
+
|
35
|
+
assert_equal(expected, Tariff.count(:group => :start_date))
|
32
36
|
end
|
33
37
|
|
34
38
|
def test_products
|
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:
|
4
|
+
hash: 9
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 3
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 3.1.
|
9
|
+
- 5
|
10
|
+
version: 3.1.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Dr Nic Williams
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-03-
|
19
|
+
date: 2011-03-24 00:00:00 -06:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -66,6 +66,7 @@ files:
|
|
66
66
|
- init.rb
|
67
67
|
- install.rb
|
68
68
|
- loader.rb
|
69
|
+
- lib/composite_primary_keys/arel_extensions.rb
|
69
70
|
- lib/composite_primary_keys/associations/association_proxy.rb
|
70
71
|
- lib/composite_primary_keys/associations/has_and_belongs_to_many_association.rb
|
71
72
|
- lib/composite_primary_keys/associations/has_many_association.rb
|
@@ -183,6 +184,7 @@ files:
|
|
183
184
|
- test/plugins/pagination_helper.rb
|
184
185
|
- test/README_tests.txt
|
185
186
|
- test/setup.rb
|
187
|
+
- test/test_arel.rb
|
186
188
|
- test/test_associations.rb
|
187
189
|
- test/test_attributes.rb
|
188
190
|
- test/test_attribute_methods.rb
|
@@ -234,7 +236,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
234
236
|
requirements: []
|
235
237
|
|
236
238
|
rubyforge_project: compositekeys
|
237
|
-
rubygems_version: 1.6.
|
239
|
+
rubygems_version: 1.6.2
|
238
240
|
signing_key:
|
239
241
|
specification_version: 3
|
240
242
|
summary: Composite key support for ActiveRecord
|
@@ -245,6 +247,7 @@ test_files:
|
|
245
247
|
- test/hash_tricks.rb
|
246
248
|
- test/README_tests.txt
|
247
249
|
- test/setup.rb
|
250
|
+
- test/test_arel.rb
|
248
251
|
- test/test_associations.rb
|
249
252
|
- test/test_attributes.rb
|
250
253
|
- test/test_attribute_methods.rb
|