composite_primary_keys 6.0.7 → 6.0.8

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