composite_primary_keys 3.1.4 → 3.1.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|