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.
@@ -1,7 +1,14 @@
1
- == 3.1.3 2011-03-05
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
- #module ActiveRecord
2
- # module Calculations
3
- # alias :execute_simple_calculation_original :execute_simple_calculation
4
- #
5
- # def execute_simple_calculation(operation, column_name, distinct)
6
- # if column_name.kind_of?(Array)
7
- # execute_simple_calculation_cpk(operation, column_name, distinct)
8
- # else
9
- # execute_simple_calculation_original(operation, column_name, distinct)
10
- # end
11
- # end
12
- #
13
- # def execute_simple_calculation_cpk(operation, column_name, distinct)
14
- # # SELECT COUNT(field1, field2) doens't work so make a subquery
15
- # # like SELECT COUNT(*) FROM (SELECT DISTINCT field1, field2)
16
- #
17
- # columns = column_name.map do |primary_key_column|
18
- # table[primary_key_column]
19
- # end
20
- #
21
- # subquery = clone.project(columns)
22
- # subquery = "(#{subquery.to_sql}) AS calculation_subquery"
23
- # relation = Arel::Table.new(Arel::SqlLiteral.new(subquery))#.project(Arel::SqlLiteral.new('*').count)
24
- # puts relation.to_sql
25
- #
26
- # #projection = "DISTINCT #{columns.join(',')}"
27
- # #subquery = "(#{table.project(projection).to_sql}) AS subquery"
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.where(ids_predicate(id)) if id
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
- # 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(ids_predicate(id)) if id
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,7 +2,7 @@ module ActiveRecord
2
2
  module Reflection
3
3
  class AssociationReflection
4
4
  def derive_primary_key
5
- result = if options[:foreign_key]
5
+ if options[:foreign_key]
6
6
  options[:foreign_key]
7
7
  elsif belongs_to?
8
8
  #CPK
@@ -2,35 +2,49 @@ module CompositePrimaryKeys
2
2
  module ActiveRecord
3
3
  module Relation
4
4
  module InstanceMethods
5
- def ids_predicate(id)
6
- predicate = nil
5
+ def where_cpk_id(id)
6
+ relation = clone
7
7
 
8
- if id.kind_of?(CompositePrimaryKeys::CompositeKeys)
9
- id = [id]
8
+ predicates = self.primary_keys.zip(Array(id)).map do |key, value|
9
+ table[key].eq(value)
10
10
  end
11
-
12
- id.each do |composite_id|
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
- where(ids_predicate(id_or_array)).delete_all
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(id)
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
- find(id).destroy
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
@@ -2,7 +2,7 @@ module CompositePrimaryKeys
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 3
4
4
  MINOR = 1
5
- TINY = 4
5
+ TINY = 5
6
6
  STRING = [MAJOR, MINOR, TINY].join('.')
7
7
  end
8
8
  end
@@ -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
@@ -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
- assert_equal(2, Tariff.count(:group => :start_date))
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: 11
4
+ hash: 9
5
5
  prerelease:
6
6
  segments:
7
7
  - 3
8
8
  - 1
9
- - 4
10
- version: 3.1.4
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-06 00:00:00 -07:00
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.1
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