composite_primary_keys 6.0.7 → 6.0.8

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: add6bac7bcaa5ca9b40c11e99df452b921b962ae
4
- data.tar.gz: d1dd46cc248802f32c061f349c7d8f2158268cf9
3
+ metadata.gz: e0407c008d66e10820394e98a97bb7a507d0226a
4
+ data.tar.gz: 25d4c43eb87731e104c3ec486e94a20b9568f0bf
5
5
  SHA512:
6
- metadata.gz: 1dbf3af753f80209f70ccc15b2dfbc08a8bca681489a114bebf5c4d442f87c6b7dd06c4245ea83da7d02b904f1bc853634a8030deef31b0a95bd823a4f5a8efa
7
- data.tar.gz: b293046f7cc2c73ca0edb6d462588988101c83f9fb34c6841281da4f614990952d4fefbdacd651f39540c3c425526253dc7821a208b7c7bf9a98797412e3dd1e
6
+ metadata.gz: 007219da8c4b82d562742f361516772b7f74d4f97e6d065ef01b526dbb9b6047e18b2445dcf3054070d7ff129da0d7a29f5ff78fc55ef49f22503080fa894a42
7
+ data.tar.gz: b712e6fb1b0d39c530b6c54c9e6dddd81bcf6552989f95b12160612379aaa27ee671ae6d1fc85a40d698c933ff2fc65eba2777b1e060ac94380f3c7ce6a603cb
@@ -1,3 +1,9 @@
1
+ == 6.0.08 (2015-01-24)
2
+
3
+ * Fix habtm association #delete_records (Uros Jurglic)
4
+ * Support optimistic locking (Toshio Maki)
5
+ * Remove singleton classes on CPK relations (Nicolás Hock Isaza)
6
+
1
7
  == 6.0.7 (2014-10-06)
2
8
 
3
9
  * Support Rails 4.0.6 (Tom Hughes)
@@ -52,8 +52,10 @@ require 'active_record/associations/preloader/has_and_belongs_to_many'
52
52
  require 'active_model/dirty'
53
53
 
54
54
  require 'active_record/attribute_methods/dirty'
55
+ require 'active_record/attribute_methods/primary_key'
55
56
  require 'active_record/attribute_methods/read'
56
57
  require 'active_record/attribute_methods/write'
58
+ require 'active_record/locking/optimistic'
57
59
  require 'active_record/nested_attributes'
58
60
 
59
61
  require 'active_record/connection_adapters/abstract_adapter'
@@ -68,6 +70,7 @@ require 'active_record/validations/uniqueness'
68
70
 
69
71
  # CPK files
70
72
  require 'composite_primary_keys/persistence'
73
+ require 'composite_primary_keys/locking/optimistic'
71
74
  require 'composite_primary_keys/active_record_overides'
72
75
  require 'composite_primary_keys/base'
73
76
  require 'composite_primary_keys/core'
@@ -92,6 +95,7 @@ require 'composite_primary_keys/associations/preloader/has_and_belongs_to_many'
92
95
  require 'composite_primary_keys/dirty'
93
96
 
94
97
  require 'composite_primary_keys/attribute_methods/dirty'
98
+ require 'composite_primary_keys/attribute_methods/primary_key'
95
99
  require 'composite_primary_keys/attribute_methods/read'
96
100
  require 'composite_primary_keys/attribute_methods/write'
97
101
  require 'composite_primary_keys/nested_attributes'
@@ -105,3 +109,5 @@ require 'composite_primary_keys/relation/finder_methods'
105
109
  require 'composite_primary_keys/relation/query_methods'
106
110
 
107
111
  require 'composite_primary_keys/validations/uniqueness'
112
+
113
+ require 'composite_primary_keys/composite_relation'
@@ -49,7 +49,8 @@ module ActiveRecord
49
49
 
50
50
  predicate1 = cpk_id_predicate(relation, Array(reflection.foreign_key), Array(owner.id))
51
51
  predicate2 = cpk_in_predicate(relation, Array(reflection.association_foreign_key), records.map { |x| x.id }) unless records == :all
52
- stmt = relation.where(predicate1.and(predicate2)).compile_delete
52
+ conds = predicate2.nil?? predicate1 : predicate1.and(predicate2)
53
+ stmt = relation.where(conds).compile_delete
53
54
 
54
55
  owner.class.connection.delete stmt.to_sql
55
56
  end
@@ -0,0 +1,17 @@
1
+ module ActiveRecord
2
+ module AttributeMethods
3
+ module PrimaryKey
4
+ def id_was
5
+ sync_with_transaction_state
6
+
7
+ if self.composite?
8
+ self.class.primary_keys.map do |key_attr|
9
+ attribute_changed?(key_attr) ? changed_attributes[key_attr] : self.ids_hash[key_attr]
10
+ end
11
+ else
12
+ attribute_was(self.class.primary_key)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -4,6 +4,7 @@ module ActiveRecord
4
4
 
5
5
  class Base
6
6
  include CompositePrimaryKeys::ActiveRecord::Persistence
7
+ include CompositePrimaryKeys::ActiveRecord::Locking::Optimistic
7
8
 
8
9
  INVALID_FOR_COMPOSITE_KEYS = 'Not appropriate for composite primary keys'
9
10
  NOT_IMPLEMENTED_YET = 'Not implemented for composite primary keys yet'
@@ -0,0 +1,44 @@
1
+ module CompositePrimaryKeys
2
+ module CompositeRelation
3
+ include CompositePrimaryKeys::ActiveRecord::Batches
4
+ include CompositePrimaryKeys::ActiveRecord::Calculations
5
+ include CompositePrimaryKeys::ActiveRecord::FinderMethods
6
+ include CompositePrimaryKeys::ActiveRecord::QueryMethods
7
+
8
+ def delete(id_or_array)
9
+ # Without CPK:
10
+ # where(primary_key => id_or_array).delete_all
11
+
12
+ id_or_array = if id_or_array.kind_of?(CompositePrimaryKeys::CompositeKeys)
13
+ [id_or_array]
14
+ else
15
+ Array(id_or_array)
16
+ end
17
+
18
+ id_or_array.each do |id|
19
+ where(cpk_id_predicate(table, self.primary_key, id)).delete_all
20
+ end
21
+ end
22
+
23
+ def destroy(id_or_array)
24
+ # Without CPK:
25
+ #if id.is_a?(Array)
26
+ # id.map { |one_id| destroy(one_id) }
27
+ #else
28
+ # find(id).destroy
29
+ #end
30
+
31
+ id_or_array = if id_or_array.kind_of?(CompositePrimaryKeys::CompositeKeys)
32
+ [id_or_array]
33
+ else
34
+ Array(id_or_array)
35
+ end
36
+
37
+ id_or_array.each do |id|
38
+ where(cpk_id_predicate(table, self.primary_key, id)).each do |record|
39
+ record.destroy
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,51 @@
1
+ module CompositePrimaryKeys
2
+ module ActiveRecord
3
+ module Locking
4
+ module Optimistic
5
+ private
6
+ def _update_record(attribute_names = @attributes.keys) #:nodoc:
7
+ return super unless locking_enabled?
8
+ return 0 if attribute_names.empty?
9
+
10
+ lock_col = self.class.locking_column
11
+ previous_lock_value = send(lock_col).to_i
12
+ increment_lock
13
+
14
+ attribute_names += [lock_col]
15
+ attribute_names.uniq!
16
+
17
+ begin
18
+ relation = self.class.unscoped
19
+
20
+ if self.composite?
21
+ stmt = relation.where(
22
+ relation.cpk_id_predicate(relation.table, self.class.primary_key, id_was).and(
23
+ relation.table[lock_col].eq(self.class.quote_value(previous_lock_value, column_for_attribute(lock_col)))
24
+ )
25
+ ).arel.compile_update(arel_attributes_with_values_for_update(attribute_names))
26
+ else
27
+ stmt = relation.where(
28
+ relation.table[self.class.primary_key].eq(id).and(
29
+ relation.table[lock_col].eq(self.class.quote_value(previous_lock_value, column_for_attribute(lock_col)))
30
+ )
31
+ ).arel.compile_update(arel_attributes_with_values_for_update(attribute_names))
32
+ end
33
+
34
+ affected_rows = self.class.connection.update stmt
35
+
36
+ unless affected_rows == 1
37
+ raise ::ActiveRecord::StaleObjectError.new(self, "update")
38
+ end
39
+
40
+ affected_rows
41
+
42
+ # If something went wrong, revert the version.
43
+ rescue Exception
44
+ send(lock_col + '=', previous_lock_value)
45
+ raise
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,71 +1,25 @@
1
1
  module ActiveRecord
2
2
  class Relation
3
3
  def add_cpk_support
4
- class << self
5
- include CompositePrimaryKeys::ActiveRecord::Batches
6
- include CompositePrimaryKeys::ActiveRecord::Calculations
7
- include CompositePrimaryKeys::ActiveRecord::FinderMethods
8
- include CompositePrimaryKeys::ActiveRecord::QueryMethods
9
-
10
-
11
- def delete(id_or_array)
12
- # Without CPK:
13
- # where(primary_key => id_or_array).delete_all
14
-
15
- id_or_array = if id_or_array.kind_of?(CompositePrimaryKeys::CompositeKeys)
16
- [id_or_array]
17
- else
18
- Array(id_or_array)
19
- end
20
-
21
- id_or_array.each do |id|
22
- where(cpk_id_predicate(table, self.primary_key, id)).delete_all
23
- end
24
- end
25
-
26
- def destroy(id_or_array)
27
- # Without CPK:
28
- #if id.is_a?(Array)
29
- # id.map { |one_id| destroy(one_id) }
30
- #else
31
- # find(id).destroy
32
- #end
33
-
34
- id_or_array = if id_or_array.kind_of?(CompositePrimaryKeys::CompositeKeys)
35
- [id_or_array]
36
- else
37
- Array(id_or_array)
38
- end
39
-
40
- id_or_array.each do |id|
41
- where(cpk_id_predicate(table, self.primary_key, id)).each do |record|
42
- record.destroy
43
- end
44
- end
45
- end
46
- end
4
+ extend CompositePrimaryKeys::CompositeRelation
47
5
  end
48
6
 
49
- def add_cpk_where_values_hash
50
- class << self
51
- def where_values_hash(relation_table_name = table_name)
52
- # CPK adds this so that it finds the Equality nodes beneath the And node:
53
- nodes_from_and = with_default_scope.where_values.grep(Arel::Nodes::And).map {|and_node| and_node.children.grep(Arel::Nodes::Equality) }.flatten
7
+ alias :where_values_hash_without_cpk :where_values_hash
8
+ def where_values_hash(relation_table_name = table_name)
9
+ # CPK adds this so that it finds the Equality nodes beneath the And node:
10
+ nodes_from_and = with_default_scope.where_values.grep(Arel::Nodes::And).map {|and_node| and_node.children.grep(Arel::Nodes::Equality) }.flatten
54
11
 
55
- equalities = (nodes_from_and + with_default_scope.where_values.grep(Arel::Nodes::Equality)).find_all { |node|
56
- node.left.relation.name == relation_table_name
57
- }
12
+ equalities = (nodes_from_and + with_default_scope.where_values.grep(Arel::Nodes::Equality)).find_all { |node|
13
+ node.left.relation.name == relation_table_name
14
+ }
58
15
 
59
- Hash[equalities.map { |where| [where.left.name, where.right] }]
60
- end
61
- end
16
+ Hash[equalities.map { |where| [where.left.name, where.right] }]
62
17
  end
63
18
 
64
19
  alias :initialize_without_cpk :initialize
65
20
  def initialize(klass, table, values = {})
66
21
  initialize_without_cpk(klass, table, values)
67
22
  add_cpk_support if klass && klass.composite?
68
- add_cpk_where_values_hash
69
23
  end
70
24
 
71
25
  alias :initialize_copy_without_cpk :initialize_copy
@@ -2,7 +2,7 @@ module CompositePrimaryKeys
2
2
  module VERSION
3
3
  MAJOR = 6
4
4
  MINOR = 0
5
- TINY = 7
5
+ TINY = 8
6
6
  STRING = [MAJOR, MINOR, TINY].join('.')
7
7
  end
8
8
  end
@@ -6,6 +6,7 @@ require 'composite_primary_keys'
6
6
 
7
7
  require 'active_support/test_case'
8
8
  require 'minitest/autorun'
9
+ require 'mocha/mini_test'
9
10
 
10
11
  # Now load the connection spec
11
12
  require File.join(PROJECT_ROOT, "test", "connections", "connection_spec")
@@ -27,13 +28,13 @@ I18n.config.enforce_available_locales = true
27
28
 
28
29
  class ActiveSupport::TestCase
29
30
  include ActiveRecord::TestFixtures
30
-
31
+
31
32
  self.fixture_path = File.dirname(__FILE__) + "/fixtures/"
32
33
  self.use_instantiated_fixtures = false
33
34
  self.use_transactional_fixtures = true
34
35
 
35
36
  def assert_date_from_db(expected, actual, message = nil)
36
- # SQL Server doesn't have a separate column type just for dates,
37
+ # SQL Server doesn't have a separate column type just for dates,
37
38
  # so the time is in the string and incorrectly formatted
38
39
  if current_adapter?(:SQLServerAdapter)
39
40
  assert_equal expected.strftime("%Y/%m/%d 00:00:00"), actual.strftime("%Y/%m/%d 00:00:00")
@@ -60,11 +61,11 @@ class ActiveSupport::TestCase
60
61
  def assert_no_queries(&block)
61
62
  assert_queries(0, &block)
62
63
  end
63
-
64
+
64
65
  cattr_accessor :classes
65
66
 
66
67
  protected
67
-
68
+
68
69
  def testing_with(&block)
69
70
  classes.keys.each do |key_test|
70
71
  @key_test = key_test
@@ -75,15 +76,15 @@ class ActiveSupport::TestCase
75
76
  yield
76
77
  end
77
78
  end
78
-
79
+
79
80
  def first_id
80
81
  ids = (1..@primary_keys.length).map {|num| 1}
81
82
  composite? ? ids.to_composite_ids : ids.first
82
83
  end
83
-
84
+
84
85
  def composite?
85
86
  @key_test != :single
86
- end
87
+ end
87
88
 
88
89
  # Oracle metadata is in all caps.
89
90
  def with_quoted_identifiers(s)
@@ -1,8 +1,8 @@
1
1
  CREATE TABLE reference_types (
2
- reference_type_id integer NOT NULL generated by default as identity (start with 100, increment by 1, no cache),
3
- type_label varchar(50) default NULL,
4
- abbreviation varchar(50) default NULL,
5
- description varchar(50) default NULL,
2
+ reference_type_id integer NOT NULL generated by default as identity (start with 100, increment by 1, no cache),
3
+ type_label varchar(50) default NULL,
4
+ abbreviation varchar(50) default NULL,
5
+ description varchar(50) default NULL,
6
6
  PRIMARY KEY (reference_type_id)
7
7
  );
8
8
 
@@ -74,7 +74,7 @@ CREATE TABLE groups (
74
74
  id integer NOT NULL ,
75
75
  name varchar(50) NOT NULL,
76
76
  PRIMARY KEY (id)
77
- );
77
+ );
78
78
 
79
79
  CREATE TABLE memberships (
80
80
  user_id integer NOT NULL,
@@ -91,17 +91,18 @@ CREATE TABLE membership_statuses (
91
91
  );
92
92
 
93
93
  create table restaurants (
94
- franchise_id integer not null,
95
- store_id integer not null,
96
- name varchar(100),
97
- primary key (franchise_id, store_id)
94
+ franchise_id integer not null,
95
+ store_id integer not null,
96
+ name varchar(100),
97
+ lock_version integer default 0,
98
+ primary key (franchise_id, store_id)
98
99
  );
99
100
 
100
101
  create table restaurants_suburbs (
101
- franchise_id integer not null,
102
- store_id integer not null,
103
- city_id integer not null,
104
- suburb_id integer not null
102
+ franchise_id integer not null,
103
+ store_id integer not null,
104
+ city_id integer not null,
105
+ suburb_id integer not null
105
106
  );
106
107
 
107
108
  create table products_restaurants (
@@ -109,3 +110,9 @@ create table products_restaurants (
109
110
  franchise_id integer not null,
110
111
  store_id integer not null
111
112
  );
113
+
114
+ create table model_with_callbacks (
115
+ reference_type_id integer,
116
+ reference_code integer NOT NULL,
117
+ PRIMARY KEY (reference_type_id,reference_code)
118
+ );
@@ -1,17 +1,18 @@
1
- drop table MEMBERSHIPS;
2
- drop table REFERENCE_CODES;
3
- drop table TARIFFS;
4
- drop table ARTICLES;
5
- drop table GROUPS;
6
- drop table MEMBERSHIP_STATUSES;
7
- drop table READINGS;
8
- drop table REFERENCE_TYPES;
9
- drop table STREETS;
10
- drop table PRODUCTS;
11
- drop table USERS;
12
- drop table SUBURBS;
13
- drop table PRODUCT_TARIFFS;
1
+ drop table MEMBERSHIPS;
2
+ drop table REFERENCE_CODES;
3
+ drop table TARIFFS;
4
+ drop table ARTICLES;
5
+ drop table GROUPS;
6
+ drop table MEMBERSHIP_STATUSES;
7
+ drop table READINGS;
8
+ drop table REFERENCE_TYPES;
9
+ drop table STREETS;
10
+ drop table PRODUCTS;
11
+ drop table USERS;
12
+ drop table SUBURBS;
13
+ drop table PRODUCT_TARIFFS;
14
14
  drop table KITCHEN_SINK;
15
15
  drop table RESTAURANTS;
16
16
  drop table RESTAURANTS_SUBURBS;
17
17
  drop table PRODUCTS_RESTAURANTS;
18
+ drop table MODEL_WITH_CALLBACKS;
@@ -123,6 +123,7 @@ create table restaurants (
123
123
  franchise_id int not null,
124
124
  store_id int not null,
125
125
  name varchar(100),
126
+ lock_version int default 0,
126
127
  primary key (franchise_id, store_id)
127
128
  );
128
129
 
@@ -190,3 +191,9 @@ create table employees_groups (
190
191
  employee_id int not null,
191
192
  group_id int not null
192
193
  );
194
+
195
+ create table model_with_callbacks (
196
+ reference_type_id int not null,
197
+ reference_code int not null,
198
+ primary key (reference_type_id, reference_code)
199
+ );
@@ -40,3 +40,4 @@ drop sequence students_seq;
40
40
  drop table seats;
41
41
  drop table capitols;
42
42
  drop table products_restaurants;
43
+ drop table model_with_callbacks;
@@ -131,6 +131,7 @@ create table restaurants (
131
131
  franchise_id number(11) not null,
132
132
  store_id number(11) not null,
133
133
  name varchar(100),
134
+ lock_version number(11) default 0,
134
135
  constraint restaurants_pk primary key (franchise_id, store_id)
135
136
  );
136
137
 
@@ -205,3 +206,8 @@ create table employees_groups (
205
206
  group_id int not null
206
207
  );
207
208
 
209
+ create table model_with_callbacks(
210
+ reference_type_id number(11),
211
+ reference_code number(11),
212
+ constraint model_with_callbacks_pk primary key (reference_type_id, reference_code)
213
+ );
@@ -125,6 +125,7 @@ create table restaurants (
125
125
  franchise_id int not null,
126
126
  store_id int not null,
127
127
  name varchar(100),
128
+ lock_version int default 0,
128
129
  primary key (franchise_id, store_id)
129
130
  );
130
131
 
@@ -192,3 +193,9 @@ create table employees_groups (
192
193
  employee_id int not null,
193
194
  group_id int not null
194
195
  );
196
+
197
+ create table model_with_callbacks(
198
+ reference_type_id int,
199
+ reference_code int not null,
200
+ primary key (reference_type_id, reference_code)
201
+ );
@@ -83,7 +83,7 @@ create table membership_statuses (
83
83
  id integer not null primary key autoincrement,
84
84
  user_id int not null,
85
85
  group_id int not null,
86
- status varchar(50) not null
86
+ status varchar(50) not null
87
87
  );
88
88
 
89
89
  create table departments (
@@ -111,48 +111,49 @@ create table hacks (
111
111
  );
112
112
 
113
113
  create table restaurants (
114
- franchise_id integer not null,
115
- store_id integer not null,
116
- name varchar(100),
117
- primary key (franchise_id, store_id)
114
+ franchise_id integer not null,
115
+ store_id integer not null,
116
+ name varchar(100),
117
+ lock_version integer default 0,
118
+ primary key (franchise_id, store_id)
118
119
  );
119
120
 
120
121
  create table restaurants_suburbs (
121
- franchise_id integer not null,
122
- store_id integer not null,
123
- city_id integer not null,
124
- suburb_id integer not null
122
+ franchise_id integer not null,
123
+ store_id integer not null,
124
+ city_id integer not null,
125
+ suburb_id integer not null
125
126
  );
126
127
 
127
128
  create table dorms (
128
- id integer not null primary key autoincrement
129
+ id integer not null primary key autoincrement
129
130
  );
130
131
 
131
132
  create table rooms (
132
- dorm_id integer not null,
133
- room_id integer not null,
134
- primary key (dorm_id, room_id)
133
+ dorm_id integer not null,
134
+ room_id integer not null,
135
+ primary key (dorm_id, room_id)
135
136
  );
136
137
 
137
138
  create table room_attributes (
138
- id integer not null primary key autoincrement,
139
- name varchar(50)
139
+ id integer not null primary key autoincrement,
140
+ name varchar(50)
140
141
  );
141
142
 
142
143
  create table room_attribute_assignments (
143
- dorm_id integer not null,
144
- room_id integer not null,
145
- room_attribute_id integer not null
144
+ dorm_id integer not null,
145
+ room_id integer not null,
146
+ room_attribute_id integer not null
146
147
  );
147
148
 
148
149
  create table students (
149
- id integer not null primary key autoincrement
150
+ id integer not null primary key autoincrement
150
151
  );
151
152
 
152
153
  create table room_assignments (
153
- student_id integer not null,
154
- dorm_id integer not null,
155
- room_id integer not null
154
+ student_id integer not null,
155
+ dorm_id integer not null,
156
+ room_id integer not null
156
157
  );
157
158
 
158
159
  create table seats (
@@ -170,8 +171,8 @@ create table capitols (
170
171
 
171
172
  create table products_restaurants (
172
173
  product_id integer not null,
173
- franchise_id integer not null,
174
- store_id integer not null
174
+ franchise_id integer not null,
175
+ store_id integer not null
175
176
  );
176
177
 
177
178
  create table employees_groups (
@@ -179,3 +180,8 @@ create table employees_groups (
179
180
  group_id integer not null
180
181
  );
181
182
 
183
+ create table model_with_callbacks(
184
+ reference_type_id int(11),
185
+ reference_code int(11) not null,
186
+ primary key (reference_type_id, reference_code)
187
+ );
@@ -83,4 +83,7 @@ DROP TABLE capitols;
83
83
  go
84
84
 
85
85
  DROP TABLE products_restaurants;
86
- go
86
+ go
87
+
88
+ DROP TABLE model_with_callbacks;
89
+ go
@@ -28,7 +28,7 @@ CREATE TABLE tariffs (
28
28
  [tariff_id] [int],
29
29
  [start_date] [date],
30
30
  [amount] [int] NULL
31
- CONSTRAINT [tariffs_pk] PRIMARY KEY
31
+ CONSTRAINT [tariffs_pk] PRIMARY KEY
32
32
  ( [tariff_id], [start_date] )
33
33
  );
34
34
  go
@@ -88,7 +88,7 @@ go
88
88
  CREATE TABLE memberships (
89
89
  user_id [int] NOT NULL,
90
90
  group_id [int] NOT NULL
91
- CONSTRAINT [memberships_pk] PRIMARY KEY
91
+ CONSTRAINT [memberships_pk] PRIMARY KEY
92
92
  ( [user_id], [group_id] )
93
93
  );
94
94
  go
@@ -133,8 +133,9 @@ go
133
133
  CREATE TABLE restaurants (
134
134
  franchise_id [int] NOT NULL,
135
135
  store_id [int] NOT NULL,
136
- name [varchar](100)
137
- CONSTRAINT [restaurants_pk] PRIMARY KEY CLUSTERED
136
+ name [varchar](100),
137
+ lock_version [int] DEFAULT 0
138
+ CONSTRAINT [restaurants_pk] PRIMARY KEY CLUSTERED
138
139
  ( [franchise_id], [store_id] )
139
140
  );
140
141
  go
@@ -155,7 +156,7 @@ go
155
156
  CREATE TABLE rooms (
156
157
  dorm_id [int] NOT NULL,
157
158
  room_id [int] NOT NULL,
158
- CONSTRAINT [rooms_pk] PRIMARY KEY CLUSTERED
159
+ CONSTRAINT [rooms_pk] PRIMARY KEY CLUSTERED
159
160
  ( [dorm_id], [room_id] )
160
161
  );
161
162
  go
@@ -197,7 +198,7 @@ go
197
198
  CREATE TABLE capitols (
198
199
  country varchar(450) NOT NULL,
199
200
  city varchar(450) NOT NULL
200
- CONSTRAINT [capitols_pk] PRIMARY KEY
201
+ CONSTRAINT [capitols_pk] PRIMARY KEY
201
202
  ( [country], [city] )
202
203
  );
203
204
  go
@@ -207,4 +208,12 @@ CREATE TABLE products_restaurants (
207
208
  franchise_id [int] NOT NULL,
208
209
  store_id [int] NOT NULL
209
210
  );
210
- go
211
+ go
212
+
213
+ CREATE TABLE model_with_callbacks (
214
+ reference_type_id [int],
215
+ reference_code [int],
216
+ CONSTRAINT [model_with_callbacks_pk] PRIMARY KEY
217
+ ( [reference_type_id], [reference_code] )
218
+ );
219
+ go
@@ -1,3 +1,3 @@
1
1
  class Dorm < ActiveRecord::Base
2
- has_many :rooms, :include => :room_attributes, :primary_key => [:id]
3
- end
2
+ has_many :rooms, -> { includes(:room_attributes) }, :primary_key => [:id]
3
+ end
@@ -0,0 +1,39 @@
1
+ class ModelWithCallback < ActiveRecord::Base
2
+ after_save :after_save_method
3
+ before_save :before_save_method
4
+ around_save :around_save_method
5
+
6
+ after_create :after_create_method
7
+ before_create :before_create_method
8
+ around_create :around_create_method
9
+
10
+ after_update :after_update_method
11
+ before_update :before_update_method
12
+ around_update :around_update_method
13
+
14
+ after_destroy :after_destroy_method
15
+ before_destroy :before_destroy_method
16
+ around_destroy :around_destroy_method
17
+
18
+ private
19
+
20
+ # Save callbacks
21
+ def after_save_method ; end
22
+ def before_save_method ; end
23
+ def around_save_method ; yield ; end
24
+
25
+ # Create callbacks
26
+ def after_create_method ; end
27
+ def before_create_method ; end
28
+ def around_create_method ; yield ;end
29
+
30
+ # Update callbacks
31
+ def after_update_method ; end
32
+ def before_update_method ; end
33
+ def around_update_method ; yield ; end
34
+
35
+ # Destroy callbacks
36
+ def after_destroy_method ; end
37
+ def before_destroy_method ; end
38
+ def around_destroy_method ; yield ; end
39
+ end
@@ -0,0 +1,3 @@
1
+ random:
2
+ reference_type_id: 1
3
+ reference_code: 1
@@ -1,6 +1,6 @@
1
1
  class Suburb < ActiveRecord::Base
2
2
  self.primary_keys = :city_id, :suburb_id
3
3
  has_many :streets, :foreign_key => [:city_id, :suburb_id]
4
- has_many :first_streets, :foreign_key => [:city_id, :suburb_id],
5
- :class_name => 'Street', :conditions => "streets.name = 'First Street'"
6
- end
4
+ has_many :first_streets, -> { where "streets.name = 'First Street'" },
5
+ :foreign_key => [:city_id, :suburb_id], :class_name => 'Street'
6
+ end
@@ -0,0 +1,36 @@
1
+ require File.expand_path('../abstract_unit', __FILE__)
2
+
3
+ def has_callbacks(obj, action, options = {})
4
+ obj.expects(:"before_#{action}_method")
5
+ obj.expects(:"after_#{action}_method")
6
+ obj.expects(:"around_#{action}_method")
7
+ end
8
+
9
+ class TestCallbacks < ActiveSupport::TestCase
10
+ fixtures :model_with_callbacks
11
+
12
+ def test_save_callbacks
13
+ obj = ModelWithCallback.first
14
+ has_callbacks(obj, :save)
15
+ obj.save
16
+ end
17
+
18
+ def test_create_callbacks
19
+ obj = ModelWithCallback.new
20
+ has_callbacks(obj, :create)
21
+ obj.save!
22
+ end
23
+
24
+ def test_update_callbacks
25
+ obj = ModelWithCallback.first
26
+ has_callbacks(obj, :update)
27
+ obj.reference_code = 4
28
+ obj.save!
29
+ end
30
+
31
+ def test_destroy_callbacks
32
+ obj = ModelWithCallback.first
33
+ has_callbacks(obj, :destroy)
34
+ obj.destroy
35
+ end
36
+ end
@@ -90,11 +90,13 @@ class TestDelete < ActiveSupport::TestCase
90
90
  end
91
91
 
92
92
  def test_destroy_has_and_belongs_to_many_on_non_cpk
93
- steve = employees(:steve)
94
93
  records_before = ActiveRecord::Base.connection.execute("select * from employees_groups").count
95
- steve.destroy
94
+ employee = Employee.create
95
+ employee.groups << Group.create(name: 'test')
96
+ employees_groups_count = employee.groups.count
97
+ employee.destroy!
96
98
  records_after = ActiveRecord::Base.connection.execute("select * from employees_groups").count
97
- assert_equal records_after, records_before - steve.groups.count
99
+ assert_equal records_before, records_after
98
100
  end
99
101
 
100
102
  def test_delete_not_destroy_on_cpk
@@ -0,0 +1,15 @@
1
+ require File.expand_path('../abstract_unit', __FILE__)
2
+
3
+ class TestDumpable < ActiveSupport::TestCase
4
+ fixtures :articles, :readings, :users
5
+
6
+ def test_marshal_with_simple_preload
7
+ articles = Article.preload(:readings).where(id: 1).to_a
8
+ assert_equal(Marshal.load(Marshal.dump(articles)), articles)
9
+ end
10
+
11
+ def test_marshal_with_comples_preload
12
+ articles = Article.preload({ readings: :user }).where(id: 1).to_a
13
+ assert_equal(Marshal.load(Marshal.dump(articles)), articles)
14
+ end
15
+ end
@@ -4,7 +4,7 @@ class TestEqual < ActiveSupport::TestCase
4
4
  fixtures :capitols
5
5
 
6
6
  def test_new
7
- assert_not_equal(Capitol.new, Capitol.new)
7
+ assert_not_equal(Capitol.new.object_id, Capitol.new.object_id)
8
8
  end
9
9
 
10
10
  def test_same_new
@@ -0,0 +1,18 @@
1
+ require File.expand_path('../abstract_unit', __FILE__)
2
+
3
+ class TestOptimisitic < ActiveSupport::TestCase
4
+ fixtures :restaurants
5
+
6
+ def test_update_with_stale_error
7
+ restaurant_1 = Restaurant.find([1, 1])
8
+ restaurant_1['name'] = "McDonalds renamed"
9
+
10
+ restaurant_2 = Restaurant.find([1, 1])
11
+ restaurant_2['name'] = "McDonalds renamed 2"
12
+
13
+ assert(restaurant_1.save)
14
+ assert_raise ActiveRecord::StaleObjectError do
15
+ restaurant_2.save
16
+ end
17
+ end
18
+ end
@@ -13,6 +13,7 @@
13
13
  test_habtm
14
14
  test_ids
15
15
  test_miscellaneous
16
+ test_optimistic
16
17
  test_pagination
17
18
  test_polymorphic
18
19
  test_predicates
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: composite_primary_keys
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.7
4
+ version: 6.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dr Nic Williams
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-10-06 00:00:00.000000000 Z
12
+ date: 2015-01-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -25,6 +25,20 @@ dependencies:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
27
  version: 4.0.6
28
+ - !ruby/object:Gem::Dependency
29
+ name: mocha
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: 1.1.0
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: 1.1.0
28
42
  description: Composite key support for ActiveRecord
29
43
  email:
30
44
  executables: []
@@ -50,17 +64,20 @@ files:
50
64
  - lib/composite_primary_keys/associations/preloader/belongs_to.rb
51
65
  - lib/composite_primary_keys/associations/preloader/has_and_belongs_to_many.rb
52
66
  - lib/composite_primary_keys/attribute_methods/dirty.rb
67
+ - lib/composite_primary_keys/attribute_methods/primary_key.rb
53
68
  - lib/composite_primary_keys/attribute_methods/read.rb
54
69
  - lib/composite_primary_keys/attribute_methods/write.rb
55
70
  - lib/composite_primary_keys/base.rb
56
71
  - lib/composite_primary_keys/composite_arrays.rb
57
72
  - lib/composite_primary_keys/composite_predicates.rb
73
+ - lib/composite_primary_keys/composite_relation.rb
58
74
  - lib/composite_primary_keys/connection_adapters/abstract/connection_specification_changes.rb
59
75
  - lib/composite_primary_keys/connection_adapters/abstract_adapter.rb
60
76
  - lib/composite_primary_keys/connection_adapters/postgresql_adapter.rb
61
77
  - lib/composite_primary_keys/core.rb
62
78
  - lib/composite_primary_keys/dirty.rb
63
79
  - lib/composite_primary_keys/fixtures.rb
80
+ - lib/composite_primary_keys/locking/optimistic.rb
64
81
  - lib/composite_primary_keys/nested_attributes.rb
65
82
  - lib/composite_primary_keys/persistence.rb
66
83
  - lib/composite_primary_keys/relation.rb
@@ -123,6 +140,8 @@ files:
123
140
  - test/fixtures/membership_status.rb
124
141
  - test/fixtures/membership_statuses.yml
125
142
  - test/fixtures/memberships.yml
143
+ - test/fixtures/model_with_callback.rb
144
+ - test/fixtures/model_with_callbacks.yml
126
145
  - test/fixtures/product.rb
127
146
  - test/fixtures/product_tariff.rb
128
147
  - test/fixtures/product_tariffs.yml
@@ -166,10 +185,12 @@ files:
166
185
  - test/test_attribute_methods.rb
167
186
  - test/test_attributes.rb
168
187
  - test/test_calculations.rb
188
+ - test/test_callbacks.rb
169
189
  - test/test_composite_arrays.rb
170
190
  - test/test_counter_cache.rb
171
191
  - test/test_create.rb
172
192
  - test/test_delete.rb
193
+ - test/test_dumpable.rb
173
194
  - test/test_dup.rb
174
195
  - test/test_equal.rb
175
196
  - test/test_exists.rb
@@ -178,6 +199,7 @@ files:
178
199
  - test/test_ids.rb
179
200
  - test/test_miscellaneous.rb
180
201
  - test/test_nested_attributes.rb
202
+ - test/test_optimistic.rb
181
203
  - test/test_pagination.rb
182
204
  - test/test_polymorphic.rb
183
205
  - test/test_predicates.rb
@@ -207,7 +229,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
207
229
  version: '0'
208
230
  requirements: []
209
231
  rubyforge_project: compositekeys
210
- rubygems_version: 2.4.1
232
+ rubygems_version: 2.4.5
211
233
  signing_key:
212
234
  specification_version: 4
213
235
  summary: Composite key support for ActiveRecord
@@ -221,10 +243,12 @@ test_files:
221
243
  - test/test_attributes.rb
222
244
  - test/test_attribute_methods.rb
223
245
  - test/test_calculations.rb
246
+ - test/test_callbacks.rb
224
247
  - test/test_composite_arrays.rb
225
248
  - test/test_counter_cache.rb
226
249
  - test/test_create.rb
227
250
  - test/test_delete.rb
251
+ - test/test_dumpable.rb
228
252
  - test/test_dup.rb
229
253
  - test/test_equal.rb
230
254
  - test/test_exists.rb
@@ -233,6 +257,7 @@ test_files:
233
257
  - test/test_ids.rb
234
258
  - test/test_miscellaneous.rb
235
259
  - test/test_nested_attributes.rb
260
+ - test/test_optimistic.rb
236
261
  - test/test_pagination.rb
237
262
  - test/test_polymorphic.rb
238
263
  - test/test_predicates.rb