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