schema_associations 1.2.4 → 1.2.5

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: 5a6ca1bc960ff609537ddbc4ffcad10ba5cf813c
4
- data.tar.gz: edc393be28b2f7e1613d6287614de0d0c30b7d5c
3
+ metadata.gz: dc1905f1df57594ba2e456f9453099827e62df17
4
+ data.tar.gz: f85030cb99925c5589c9499cbde3f21d177b01fc
5
5
  SHA512:
6
- metadata.gz: 96669b7a7591180b7ae45fb71fd00ea245d00010d6a70622c8a4faf0d40e21de6142f1060089ba3221585ac09e9cd4e7c1d5e0bd622b000b1dfae11664287299
7
- data.tar.gz: 9822ff73c231ead9a5a9ab932566406dfe52c99c68b556c7db6516165924016fa4beb5bea54cf7b77d910adf71a21604d2ea1c3c53e6e2dce78a21fc6d1b1d2a
6
+ metadata.gz: d747c0d7bb98aff9f230d91ec4c67d6f78d6b6d7ab75473d6486f5a8dfca9b839c949c8b3b34f41b7e0a0c42be2809cbf9f748ff47e6c7a9028262718284e15e
7
+ data.tar.gz: 8335b7d788b8fdc5f35fec400892ce3850c5227038d7a9ade9faa872c8fee03dcd71c3af340d097bd75d6fc9321fc282616accfec189ed31352fb41929922a8f
data/README.md CHANGED
@@ -7,7 +7,6 @@ on the database schema.
7
7
  [![Gem Version](https://badge.fury.io/rb/schema_associations.svg)](http://badge.fury.io/rb/schema_associations)
8
8
  [![Build Status](https://secure.travis-ci.org/SchemaPlus/schema_associations.svg)](http://travis-ci.org/SchemaPlus/schema_associations)
9
9
  [![Coverage Status](https://img.shields.io/coveralls/SchemaPlus/schema_associations.svg)](https://coveralls.io/r/SchemaPlus/schema_associations?branch=master)
10
- [![Dependency Status](https://gemnasium.com/lomba/schema_associations.svg)](https://gemnasium.com/lomba/schema_associations)
11
10
 
12
11
 
13
12
  ## Overview
@@ -22,37 +21,42 @@ defined using `belongs_to`, `has_one`, `has_many`, and
22
21
  definitions by hand. In fact, for every relation, you need to define two
23
22
  associations each listing its inverse, such as
24
23
 
25
- class Post < ActiveRecord::Base
26
- has_many :comments, :inverse_of => :post
27
- end
24
+ ```ruby
25
+ class Post < ActiveRecord::Base
26
+ has_many :comments, inverse_of: :post
27
+ end
28
28
 
29
- class Comment < ActiveReocrd::Base
30
- belongs_to :post, :inverse_of => :comments
31
- end
29
+ class Comment < ActiveRecord::Base
30
+ belongs_to :post, inverse_of: :comments
31
+ end
32
+ ```
32
33
 
33
34
  ....which isn't so DRY.
34
35
 
35
- Enter the SchemaAssociations gem. It extends ActiveRecord to automatically
36
- define the appropriate associations based on foreign key constraints in the
37
- database. SchemaAssociations builds on the
38
- [schema_plus](http://rubygems.org/gems/schema_plus) gem that automatically
39
- defines foreign key constraints. So the common case is simple -- if you have
40
- this in your migration:
36
+ Enter the SchemaAssociations gem. It extends ActiveRecord to automatically define the appropriate associations based on foreign key constraints in the database.
41
37
 
42
- create_table :posts do |t|
43
- end
38
+ SchemaAssociations works particularly well with the
39
+ [schema_auto_foreign_keys](http://github.com/SchemaPlus/schema_auto_foreign_keys) gem which automatically
40
+ defines foreign key constraints. So the common case is simple -- if you have this in your migration:
44
41
 
45
- create_table :comments do |t|
46
- t.integer post_id
47
- end
42
+ ```ruby
43
+ create_table :posts do |t|
44
+ end
45
+
46
+ create_table :comments do |t|
47
+ t.integer post_id
48
+ end
49
+ ```
48
50
 
49
51
  Then all you need for your models is:
50
52
 
51
- class Post < ActiveRecord::Base
52
- end
53
+ ```ruby
54
+ class Post < ActiveRecord::Base
55
+ end
53
56
 
54
- class Comment < ActiveRecord::Base
55
- end
57
+ class Comment < ActiveRecord::Base
58
+ end
59
+ ```
56
60
 
57
61
  and SchemaAssociations defines the appropriate associations under the hood.
58
62
 
@@ -60,34 +64,30 @@ and SchemaAssociations defines the appropriate associations under the hood.
60
64
 
61
65
  You're always free to define associations yourself, if for example you want to
62
66
  pass special options. SchemaAssociations won't clobber any existing
63
- definitions.
64
-
65
- You can also control the behavior with various options, globally via
66
- SchemaAssociations::setup or per-model via
67
- SchemaAssociations::ActiveRecord#schema_associations, such as:
68
-
69
- class Post < ActiveRecord::Base
70
- schema_associations :concise_names => false
71
- end
67
+ definitions.
72
68
 
73
- See the [SchemaAssociations::Confg RDOC](http://rubydoc.info/gems/schema_associations/SchemaAssociations/Config) for the available options.
69
+ You can also control the behavior with various options, via a global initializer and/or per-model. See the [Configuration section](#configuration) for the available options.
74
70
 
75
71
  ### This seems cool, but I'm worried about too much automagic
76
72
 
77
73
  You can globally turn off automatic creation in
78
74
  `config/initializers/schema_associations.rb`:
79
75
 
80
- SchemaAssociations.setup do |config|
81
- config.auto_create = false
82
- end
76
+ ```ruby
77
+ SchemaAssociations.setup do |config|
78
+ config.auto_create = false
79
+ end
80
+ ```
83
81
 
84
82
  Then in any model where you want automatic associations, just do
85
83
 
86
- class Post < ActiveRecord::Base
87
- schema_associations
88
- end
84
+ ```ruby
85
+ class Post < ActiveRecord::Base
86
+ schema_associations
87
+ end
88
+ ```
89
89
 
90
- You can also pass options as per above.
90
+ You can also pass options as described in [Configurtion](#configuration)
91
91
 
92
92
  ## Full Details
93
93
 
@@ -96,58 +96,70 @@ You can also pass options as per above.
96
96
  The common cases work entirely as you'd expect. For a one-to-many
97
97
  relationship using standard naming conventions:
98
98
 
99
- # migration:
100
-
101
- create_table :comments do |t|
102
- t.integer post_id
103
- end
104
-
105
- # schema_associations defines:
106
-
107
- class Post < ActiveRecord::Base
108
- has_many :comments
109
- end
110
-
111
- class Comment < ActiveReocrd::Base
112
- belongs_to :post
113
- end
99
+ ```ruby
100
+ #
101
+ # migration:
102
+ #
103
+ create_table :comments do |t|
104
+ t.integer post_id
105
+ end
106
+
107
+ #
108
+ # schema_associations defines:
109
+ #
110
+ class Post < ActiveRecord::Base
111
+ has_many :comments
112
+ end
113
+
114
+ class Comment < ActiveReocrd::Base
115
+ belongs_to :post
116
+ end
117
+ ```
114
118
 
115
119
  For a one-to-one relationship:
116
120
 
117
- # migration:
118
-
119
- create_table :comments do |t|
120
- t.integer post_id, :index => :unique # (using the :index option provided by schema_plus )
121
- end
122
-
123
- # schema_associations defines:
124
-
125
- class Post < ActiveRecord::Base
126
- has_one :comment
127
- end
128
-
129
- class Comment < ActiveReocrd::Base
130
- belongs_to :post
131
- end
121
+ ```ruby
122
+ #
123
+ # migration:
124
+ #
125
+ create_table :comments do |t|
126
+ t.integer post_id, index: :unique # (using the :index option provided by schema_plus )
127
+ end
128
+
129
+ #
130
+ # schema_associations defines:
131
+ #
132
+ class Post < ActiveRecord::Base
133
+ has_one :comment
134
+ end
135
+
136
+ class Comment < ActiveReocrd::Base
137
+ belongs_to :post
138
+ end
139
+ ```
132
140
 
133
141
  And for many-to-many relationships:
134
142
 
135
- # migration:
136
-
137
- create_table :groups_members do |t|
138
- integer :group_id
139
- integer :member_id
140
- end
141
-
142
- # schema_associations defines:
143
-
144
- class Group < ActiveReocrd::Base
145
- has_and_belongs_to_many :members
146
- end
147
-
148
- class Member < ActiveRecord::Base
149
- has_and_belongs_to_many :groups
150
- end
143
+ ```ruby
144
+ #
145
+ # migration:
146
+ #
147
+ create_table :groups_members do |t|
148
+ integer :group_id
149
+ integer :member_id
150
+ end
151
+
152
+ #
153
+ # schema_associations defines:
154
+ #
155
+ class Group < ActiveReocrd::Base
156
+ has_and_belongs_to_many :members
157
+ end
158
+
159
+ class Member < ActiveRecord::Base
160
+ has_and_belongs_to_many :groups
161
+ end
162
+ ```
151
163
 
152
164
  ### Unusual names, multiple references
153
165
 
@@ -160,139 +172,167 @@ should make this clear...
160
172
  Suppose your company hires interns, and each intern is assigned a manager and
161
173
  a mentor, who are regular employees.
162
174
 
163
- create_table :interns do |t|
164
- t.integer :manager_id, :references => :employees
165
- t.integer :mentor_id, :references => :employees
166
- end
175
+ ```ruby
176
+ create_table :interns do |t|
177
+ t.integer :manager_id, references: :employees
178
+ t.integer :mentor_id, references: :employees
179
+ end
180
+ ```
167
181
 
168
182
  SchemaAssociations defines a `belongs_to` association for each reference,
169
183
  named according to the column:
170
184
 
171
- class Intern < ActiveRecord::Base
172
- belongs_to :manager, :class_name => "Employee", :foreign_key => "manager_id"
173
- belongs_to :mentor, :class_name => "Employee", :foreign_key => "mentor_id"
174
- end
185
+ ```ruby
186
+ class Intern < ActiveRecord::Base
187
+ belongs_to :manager, class_name: "Employee", foreign_key: "manager_id"
188
+ belongs_to :mentor, class_name: "Employee", foreign_key: "mentor_id"
189
+ end
190
+ ```
175
191
 
176
192
  And the corresponding `has_many` association each gets a suffix to indicate
177
193
  which one relation it refers to:
178
194
 
179
- class Employee < ActiveRecord::Base
180
- has_many :interns_as_manager, :class_name => "Intern", :foreign_key => "manager_id"
181
- has_many :interns_as_mentor, :class_name => "Intern", :foreign_key => "mentor_id"
182
- end
195
+ ```ruby
196
+ class Employee < ActiveRecord::Base
197
+ has_many :interns_as_manager, class_name: "Intern", foreign_key: "manager_id"
198
+ has_many :interns_as_mentor, class_name: "Intern", foreign_key: "mentor_id"
199
+ end
200
+ ```
183
201
 
184
202
  ### Special case for trees
185
203
 
186
204
  If your forward relation is named "parent", SchemaAssociations names the
187
205
  reverse relation "child" or "children". That is, if you have:
188
206
 
189
- create_table :nodes
190
- t.integer :parent_id # schema_plus assumes it's a reference to this table
191
- end
207
+ ```ruby
208
+ create_table :nodes
209
+ t.integer :parent_id # schema_plus assumes it's a reference to this table
210
+ end
211
+ ```
192
212
 
193
213
  Then SchemaAssociations will define
194
214
 
195
- class Node < ActiveRecord::Base
196
- belongs_to :parent, :class_name => "Node", :foreign_key => "parent_id"
197
- has_many :children, :class_name => "Node", :foreign_key => "parent_id"
198
- end
215
+ ```ruby
216
+ class Node < ActiveRecord::Base
217
+ belongs_to :parent, class_name: "Node", foreign_key: "parent_id"
218
+ has_many :children, class_name: "Node", foreign_key: "parent_id"
219
+ end
220
+ ```
199
221
 
200
222
  ### Concise names
201
223
 
202
224
  For modularity in your tables and classes, you might use a common prefix for
203
- related objects. For example, you may have widgets each of which has a color,
204
- and might have one base that has a top color and a bottom color, from the same
205
- set of colors.
225
+ related objects. For example, you may have widgets each of which has a color, and each widget might have one frob that has a top color and a bottom color--all from the same set of colors.
206
226
 
207
- create_table :widget_colors |t|
208
- end
227
+ ```ruby
228
+ create_table :widget_colors |t|
229
+ end
209
230
 
210
- create_table :widgets do |t|
211
- t.integer :widget_color_id
212
- end
231
+ create_table :widgets do |t|
232
+ t.integer :widget_color_id
233
+ end
213
234
 
214
- create_table :widget_base
215
- t.integer :widget_id, :index => :unique
216
- t.integer :top_widget_color_id, :references => :widget_colors
217
- t.integer :bottom_widget_color_id, :references => :widget_colors
218
- end
235
+ create_table :widget_frobs
236
+ t.integer :widget_id, index: :unique
237
+ t.integer :top_widget_color_id, references: :widget_colors
238
+ t.integer :bottom_widget_color_id, references: :widget_colors
239
+ end
240
+ ```
219
241
 
220
242
  Using the full name for the associations would make your code verbose and not
221
243
  quite DRY:
222
244
 
223
- @widget.widget_color
224
- @widget.widget_base.top_widget_color
245
+ ```ruby
246
+ @widget.widget_color
247
+ @widget.widget_frob.top_widget_color
248
+ ```
225
249
 
226
250
  Instead, by default, SchemaAssociations uses concise names: shared leading
227
251
  words are removed from the association name. So instead of the above, your
228
252
  code looks like:
229
253
 
230
- @widget.color
231
- @widget.base.top_color
254
+ ```ruby
255
+ @widget.color
256
+ @widget.frob.top_color
257
+ ```
232
258
 
233
259
  i.e. these associations would be defined:
234
260
 
235
- class WidgetColor < ActiveRecord::Base
236
- has_many :widgets, :class_name => "Widget", :foreign_key => "widget_color_id"
237
- has_many :bases_as_top, :class_name => "WidgetBase", :foreign_key => "top_widget_color_id"
238
- has_many :bases_as_bottom, :class_name => "WidgetBase", :foreign_key => "bottom_widget_color_id"
239
- end
240
-
241
- class Widget < ActiveRecord::Base
242
- belongs_to :color, :class_name => "WidgetColor", :foreign_key => "widget_color_id"
243
- has_one :base, :class_name => "WidgetBase", :foreign_key => "widget_base_id"
244
- end
245
-
246
- class WidgetBase < ActiveRecord::Base
247
- belongs_to :top_color, :class_name => "WidgetColor", :foreign_key => "top_widget_color_id"
248
- belongs_to :bottom_color, :class_name => "WidgetColor", :foreign_key => "bottom_widget_color_id"
249
- belongs_to :widget, :class_name => "Widget", :foreign_key => "widget_id"
250
- end
261
+ ```ruby
262
+ class WidgetColor < ActiveRecord::Base
263
+ has_many :widgets, class_name: "Widget", foreign_key: "widget_color_id"
264
+ has_many :frobs_as_top, class_name: "WidgetFrob", foreign_key: "top_widget_color_id"
265
+ has_many :frobs_as_bottom, class_name: "WidgetFrob", foreign_key: "bottom_widget_color_id"
266
+ end
267
+
268
+ class Widget < ActiveRecord::Base
269
+ belongs_to :color, class_name: "WidgetColor", foreign_key: "widget_color_id"
270
+ has_one :frob, class_name: "WidgetFrob", foreign_key: "widget_frob_id"
271
+ end
272
+
273
+ class WidgetFrob < ActiveRecord::Base
274
+ belongs_to :top_color, class_name: "WidgetColor", foreign_key: "top_widget_color_id"
275
+ belongs_to :bottom_color, class_name: "WidgetColor", foreign_key: "bottom_widget_color_id"
276
+ belongs_to :widget, class_name: "Widget", foreign_key: "widget_id"
277
+ end
278
+ ```
251
279
 
252
280
  If you like the formality of using full names for the asociations, you can
253
- turn off concise names globally or per-model, see [SchemaAssociations::Config](http://rubydoc.info/gems/schema_associations/SchemaAssociations/Config)
281
+ turn off concise names globally or per-model, see [Configuration](#configuration).
254
282
 
255
283
  ### Ordering `has_many` using `position`
256
284
 
257
285
  If the target of a `has_many` association has a column named `position`,
258
- SchemaAssociations will specify `:order => :position` for the association.
286
+ SchemaAssociations will specify `order: :position` for the association.
259
287
  That is,
260
288
 
261
- create_table :comments do |t|
262
- t.integer post_id
263
- t.integer position
264
- end
289
+ ```ruby
290
+ create_table :comments do |t|
291
+ t.integer post_id
292
+ t.integer position
293
+ end
294
+ ```
265
295
 
266
296
  leads to
267
297
 
268
- class Post < ActiveRecord::Base
269
- has_many :comments, :order => :position
270
- end
298
+ ```ruby
299
+ class Post < ActiveRecord::Base
300
+ has_many :comments, order: :position
301
+ end
302
+ ```
271
303
 
272
- ## Table names and model class names
304
+ ## Table names, model class names, and modules
273
305
 
274
- SchemaAssociations determins the mode class name from the table name using the same convention (and helpers) that ActiveRecord uses. But sometimes you might be doing things differently. For example, in an engine you might have a prefix that goes in front of all table names, and the models might all be in a namespace.
306
+ SchemaAssociations determins the mode class name from the table name using the same convention (and helpers) that ActiveRecord uses. But sometimes you might be doing things differently. For example, in an engine you might have a prefix that goes in front of all table names, and the models might all be namespaced in a module.
275
307
 
276
308
  To that end, SchemaAssociations lets you configure mappings from a table name prefix to a model class name prefix to use instead. For example, suppose your database had tables:
277
309
 
278
- hpy_campers
279
- hpy_go_lucky
310
+ ```ruby
311
+ hpy_campers
312
+ hpy_go_lucky
313
+ ```
280
314
 
281
315
  The default model class names would be
282
316
 
283
- HpyCampers
284
- HpyGoLucky
285
-
317
+ ```ruby
318
+ HpyCampers
319
+ HpyGoLucky
320
+ ```
321
+
286
322
  But if instead you wanted
287
323
 
288
- Happy::Campers
289
- Happy::GoLucky
290
-
291
- You could set up this mapping in `config/initializers/schema_associations.rb`:
324
+ ```ruby
325
+ Happy::Campers
326
+ Happy::GoLucky
327
+ ```
328
+
329
+ you would define the mapping in the [configuration](#configuration):
292
330
 
293
- SchemaPlus.setup do |config|
294
- config.table_prefix_map["hpy_"] = "Happy::"
295
- end
331
+ ```ruby
332
+ SchemaPlus.setup do |config|
333
+ config.table_prefix_map["hpy_"] = "Happy::"
334
+ end
335
+ ```
296
336
 
297
337
  Tables names that don't start with `hpy_` will continue to use the default determination.
298
338
 
@@ -317,6 +357,61 @@ they're first needed. So you may need to search through the log file to find
317
357
  them all (and some may not be defined at all if they were never needed for the
318
358
  use cases that you logged).
319
359
 
360
+ ## Configuration
361
+
362
+ You can configure options globally in an initializer such as `config/initializers/schema_associations.rb`, e.g.
363
+
364
+ ```ruby
365
+ SchemaAssociations.setup do |config|
366
+ config.concise_names = false
367
+ end
368
+ ```
369
+
370
+ and/or override the options per-model, e.g.:
371
+
372
+ ```ruby
373
+ class MyModel < ActiveRecord::Base
374
+ schema_associations.config concise_names: false
375
+ end
376
+ ```
377
+
378
+ Here's the full list of options, with their default values:
379
+
380
+ ```ruby
381
+ SchemaAssociations.setup do |config|
382
+
383
+ # Enable/disable SchemaAssociations' automatic behavior
384
+ config.auto_create = true
385
+
386
+ # Whether to use concise naming (strip out common prefixes from class names)
387
+ config.concise_names = true
388
+
389
+ # List of association names to exclude from automatic creation.
390
+ # Value is a single name, an array of names, or nil.
391
+ config.except = nil
392
+
393
+ # List of association names to include in automatic creation.
394
+ # Value is a single name, and array of names, or nil.
395
+ config.only = nil
396
+
397
+ # List of association types to exclude from automatic creation.
398
+ # Value is one or an array of :belongs_to, :has_many, :has_one, and/or
399
+ # :has_and_belongs_to_many, or nil.
400
+ config.except_type = nil
401
+
402
+ # List of association types to include in automatic creation.
403
+ # Value is one or an array of :belongs_to, :has_many, :has_one, and/or
404
+ # :has_and_belongs_to_many, or nil.
405
+ config.only_type = nil
406
+
407
+ # Hash whose keys are possible matches at the start of table names, and
408
+ # whose corresponding values are the prefix to use in front of class
409
+ # names.
410
+ config.table_prefix_map = {}
411
+ end
412
+ ```
413
+
414
+
320
415
  ## Compatibility
321
416
 
322
417
  SchemaAssociations is tested on all combinations of:
@@ -358,6 +453,10 @@ Code coverage results will be in coverage/index.html -- it should be at 100% cov
358
453
 
359
454
  ## Release notes:
360
455
 
456
+ ### 1.2.5
457
+
458
+ * Use schema_monkey rather than Railties.
459
+
361
460
  ### 1.2.4
362
461
 
363
462
  * Bug fix: Don't fail trying to do associations for abstract classes (mysql2 only). [#11, #12] Thanks to [@dmeranda](https://github.com/dmeranda)
@@ -3,7 +3,6 @@ require 'valuable'
3
3
 
4
4
  require 'schema_associations/version'
5
5
  require 'schema_associations/active_record/associations'
6
- require 'schema_associations/railtie' if defined?(Rails)
7
6
 
8
7
  module SchemaAssociations
9
8
 
@@ -17,7 +16,7 @@ module SchemaAssociations
17
16
  # or override them per-model, e.g.:
18
17
  #
19
18
  # class MyModel < ActiveRecord::Base
20
- # schema_associations.config :concise_names => false
19
+ # schema_associations :concise_names => false
21
20
  # end
22
21
  #
23
22
  class Config < Valuable
@@ -74,7 +73,7 @@ module SchemaAssociations
74
73
  # names.
75
74
  has_value :table_prefix_map, :default => {}
76
75
 
77
- def dup #:nodoc:
76
+ def dup # :nodoc:
78
77
  self.class.new(Hash[attributes.collect{ |key, val| [key, Valuable === val ? val.class.new(val.attributes) : val] }])
79
78
  end
80
79
 
@@ -108,12 +107,6 @@ module SchemaAssociations
108
107
  yield config
109
108
  end
110
109
 
111
- def self.insert #:nodoc:
112
- return if @inserted
113
- @inserted = true
114
- ::ActiveRecord::Base.extend SchemaAssociations::ActiveRecord::Associations
115
- end
116
-
117
110
  end
118
111
 
119
- SchemaAssociations.insert unless defined? Rails::Railtie
112
+ SchemaMonkey.register SchemaAssociations
@@ -2,261 +2,254 @@ require 'ostruct'
2
2
 
3
3
  module SchemaAssociations
4
4
  module ActiveRecord
5
- module Associations #:nodoc:
6
5
 
7
- module Relation #:nodoc:
8
- def self.included(base)
9
- base.alias_method_chain :initialize, :schema_associations
10
- end
11
-
12
- def initialize_with_schema_associations(klass, *args)
13
- klass.send :_load_schema_associations_associations unless klass.nil?
14
- initialize_without_schema_associations(klass, *args)
15
- end
16
- end
6
+ module Relation
17
7
 
18
- def self.extended(base) #:nodoc:
19
- class << base
20
- alias_method_chain :reflect_on_association, :schema_associations
21
- alias_method_chain :_reflect_on_association, :schema_associations if method_defined? :_reflect_on_association
22
- alias_method_chain :reflect_on_all_associations, :schema_associations
23
- end
24
- ::ActiveRecord::Relation.send :include, Relation if defined? ::ActiveRecord::Relation
8
+ def initialize(klass, *args)
9
+ klass.send :_load_schema_associations_associations unless klass.nil?
10
+ super
25
11
  end
12
+ end
26
13
 
27
- def reflect_on_association_with_schema_associations(*args) #:nodoc:
28
- _load_schema_associations_associations
29
- reflect_on_association_without_schema_associations(*args)
30
- end
14
+ module Base
31
15
 
32
- # introduced in rails 4.1
33
- def _reflect_on_association_with_schema_associations(*args) #:nodoc:
34
- _load_schema_associations_associations
35
- _reflect_on_association_without_schema_associations(*args)
36
- end
16
+ module ClassMethods
37
17
 
38
- def reflect_on_all_associations_with_schema_associations(*args) #:nodoc:
39
- _load_schema_associations_associations
40
- reflect_on_all_associations_without_schema_associations(*args)
41
- end
18
+ def reflect_on_association(*args)
19
+ _load_schema_associations_associations
20
+ super
21
+ end
42
22
 
43
- def define_attribute_methods(*args) #:nodoc:
44
- super
45
- _load_schema_associations_associations
46
- end
23
+ # introduced in rails 4.1
24
+ def _reflect_on_association(*args)
25
+ _load_schema_associations_associations
26
+ super
27
+ end
47
28
 
48
- # Per-model override of Config options. Use via, e.g.
49
- # class MyModel < ActiveRecord::Base
50
- # schema_associations :auto_create => false
51
- # end
52
- #
53
- # If <tt>:auto_create</tt> is not specified, it is implicitly
54
- # specified as true. This allows the "non-invasive" style of using
55
- # SchemaAssociations in which you set the global Config to
56
- # <tt>auto_create = false</tt>, then in any model that you want auto
57
- # associations you simply do:
58
- #
59
- # class MyModel < ActiveRecord::Base
60
- # schema_associations
61
- # end
62
- #
63
- # Of course other options can be passed, such as
64
- #
65
- # class MyModel < ActiveRecord::Base
66
- # schema_associations :concise_names => false, :except_type => :has_and_belongs_to_many
67
- # end
68
- #
69
- #
70
- def schema_associations(opts={})
71
- @schema_associations_config = SchemaAssociations.config.merge({:auto_create => true}.merge(opts))
72
- end
29
+ def reflect_on_all_associations(*args)
30
+ _load_schema_associations_associations
31
+ super
32
+ end
73
33
 
74
- def schema_associations_config # :nodoc:
75
- @schema_associations_config ||= SchemaAssociations.config.dup
76
- end
34
+ def define_attribute_methods(*args)
35
+ super
36
+ _load_schema_associations_associations
37
+ end
77
38
 
78
- private
39
+ # Per-model override of Config options. Use via, e.g.
40
+ # class MyModel < ActiveRecord::Base
41
+ # schema_associations :auto_create => false
42
+ # end
43
+ #
44
+ # If <tt>:auto_create</tt> is not specified, it is implicitly
45
+ # specified as true. This allows the "non-invasive" style of using
46
+ # SchemaAssociations in which you set the global Config to
47
+ # <tt>auto_create = false</tt>, then in any model that you want auto
48
+ # associations you simply do:
49
+ #
50
+ # class MyModel < ActiveRecord::Base
51
+ # schema_associations
52
+ # end
53
+ #
54
+ # Of course other options can be passed, such as
55
+ #
56
+ # class MyModel < ActiveRecord::Base
57
+ # schema_associations :concise_names => false, :except_type => :has_and_belongs_to_many
58
+ # end
59
+ #
60
+ #
61
+ def schema_associations(opts={})
62
+ @schema_associations_config = SchemaAssociations.config.merge({:auto_create => true}.merge(opts))
63
+ end
79
64
 
80
- def _load_schema_associations_associations #:nodoc:
81
- return if @schema_associations_associations_loaded
82
- @schema_associations_associations_loaded = true
83
- return if abstract_class?
84
- return unless schema_associations_config.auto_create?
65
+ def schema_associations_config # :nodoc:
66
+ @schema_associations_config ||= SchemaAssociations.config.dup
67
+ end
85
68
 
86
- reverse_foreign_keys.each do | foreign_key |
87
- if foreign_key.from_table =~ /^#{table_name}_(.*)$/ || foreign_key.from_table =~ /^(.*)_#{table_name}$/
88
- other_table = $1
89
- if other_table == other_table.pluralize and connection.columns(foreign_key.from_table).any?{|col| col.name == "#{other_table.singularize}_id"}
90
- _define_association(:has_and_belongs_to_many, foreign_key, other_table)
69
+ private
70
+
71
+ def _load_schema_associations_associations
72
+ return if @schema_associations_associations_loaded
73
+ @schema_associations_associations_loaded = true
74
+ return if abstract_class?
75
+ return unless schema_associations_config.auto_create?
76
+
77
+ reverse_foreign_keys.each do | foreign_key |
78
+ if foreign_key.from_table =~ /^#{table_name}_(.*)$/ || foreign_key.from_table =~ /^(.*)_#{table_name}$/
79
+ other_table = $1
80
+ if other_table == other_table.pluralize and connection.columns(foreign_key.from_table).any?{|col| col.name == "#{other_table.singularize}_id"}
81
+ _define_association(:has_and_belongs_to_many, foreign_key, other_table)
82
+ else
83
+ _define_association(:has_one_or_many, foreign_key)
84
+ end
91
85
  else
92
86
  _define_association(:has_one_or_many, foreign_key)
93
87
  end
94
- else
95
- _define_association(:has_one_or_many, foreign_key)
96
88
  end
97
- end
98
89
 
99
- foreign_keys.each do | foreign_key |
100
- _define_association(:belongs_to, foreign_key)
90
+ foreign_keys.each do | foreign_key |
91
+ _define_association(:belongs_to, foreign_key)
92
+ end
101
93
  end
102
- end
103
94
 
104
- def _define_association(macro, fk, referencing_table_name = nil) #:nodoc:
105
- column_names = Array.wrap(fk.column)
106
- return unless column_names.size == 1
95
+ def _define_association(macro, fk, referencing_table_name = nil)
96
+ column_names = Array.wrap(fk.column)
97
+ return unless column_names.size == 1
107
98
 
108
- referencing_table_name ||= fk.from_table
109
- column_name = column_names.first
99
+ referencing_table_name ||= fk.from_table
100
+ column_name = column_names.first
110
101
 
111
- references_name = fk.to_table.singularize
112
- referencing_name = referencing_table_name.singularize
102
+ references_name = fk.to_table.singularize
103
+ referencing_name = referencing_table_name.singularize
113
104
 
114
- referencing_class_name = _get_class_name(referencing_name)
115
- references_class_name = _get_class_name(references_name)
105
+ referencing_class_name = _get_class_name(referencing_name)
106
+ references_class_name = _get_class_name(references_name)
116
107
 
117
- names = _determine_association_names(column_name.sub(/_id$/, ''), referencing_name, references_name)
108
+ names = _determine_association_names(column_name.sub(/_id$/, ''), referencing_name, references_name)
118
109
 
119
- argstr = ""
110
+ argstr = ""
120
111
 
121
112
 
122
- case macro
123
- when :has_and_belongs_to_many
124
- name = names[:has_many]
125
- opts = {:class_name => referencing_class_name, :join_table => fk.from_table, :foreign_key => column_name}
126
- when :belongs_to
127
- name = names[:belongs_to]
128
- opts = {:class_name => references_class_name, :foreign_key => column_name}
129
- if connection.indexes(referencing_table_name).any?{|index| index.unique && index.columns == [column_name]}
130
- opts[:inverse_of] = names[:has_one]
131
- else
132
- opts[:inverse_of] = names[:has_many]
133
- end
134
-
135
- when :has_one_or_many
136
- opts = {:class_name => referencing_class_name, :foreign_key => column_name, :inverse_of => names[:belongs_to]}
137
- # use connection.indexes and connection.colums rather than class
138
- # methods of the referencing class because using the class
139
- # methods would require getting the class -- which might trigger
140
- # an autoload which could start some recursion making things much
141
- # harder to debug.
142
- if connection.indexes(referencing_table_name).any?{|index| index.unique && index.columns == [column_name]}
143
- macro = :has_one
144
- name = names[:has_one]
145
- else
146
- macro = :has_many
113
+ case macro
114
+ when :has_and_belongs_to_many
147
115
  name = names[:has_many]
148
- if connection.columns(referencing_table_name).any?{ |col| col.name == 'position' }
149
- scope_block = lambda { order :position }
150
- argstr += "-> { order :position }, "
116
+ opts = {:class_name => referencing_class_name, :join_table => fk.from_table, :foreign_key => column_name}
117
+ when :belongs_to
118
+ name = names[:belongs_to]
119
+ opts = {:class_name => references_class_name, :foreign_key => column_name}
120
+ if connection.indexes(referencing_table_name).any?{|index| index.unique && index.columns == [column_name]}
121
+ opts[:inverse_of] = names[:has_one]
122
+ else
123
+ opts[:inverse_of] = names[:has_many]
124
+ end
125
+
126
+ when :has_one_or_many
127
+ opts = {:class_name => referencing_class_name, :foreign_key => column_name, :inverse_of => names[:belongs_to]}
128
+ # use connection.indexes and connection.colums rather than class
129
+ # methods of the referencing class because using the class
130
+ # methods would require getting the class -- which might trigger
131
+ # an autoload which could start some recursion making things much
132
+ # harder to debug.
133
+ if connection.indexes(referencing_table_name).any?{|index| index.unique && index.columns == [column_name]}
134
+ macro = :has_one
135
+ name = names[:has_one]
136
+ else
137
+ macro = :has_many
138
+ name = names[:has_many]
139
+ if connection.columns(referencing_table_name).any?{ |col| col.name == 'position' }
140
+ scope_block = lambda { order :position }
141
+ argstr += "-> { order :position }, "
142
+ end
151
143
  end
152
144
  end
145
+ argstr += opts.inspect[1...-1]
146
+ if (_filter_association(macro, name) && !_method_exists?(name))
147
+ _create_association(macro, name, argstr, scope_block, opts.dup)
148
+ end
153
149
  end
154
- argstr += opts.inspect[1...-1]
155
- if (_filter_association(macro, name) && !_method_exists?(name))
156
- _create_association(macro, name, argstr, scope_block, opts.dup)
157
- end
158
- end
159
150
 
160
- def _create_association(macro, name, argstr, *args)
161
- logger.debug "[schema_associations] #{self.name || self.from_table.classify}.#{macro} #{name.inspect}, #{argstr}"
162
- send macro, name, *args
163
- case
164
- when respond_to?(:subclasses) then subclasses
165
- end.each do |subclass|
166
- subclass.send :_create_association, macro, name, argstr, *args
151
+ def _create_association(macro, name, argstr, *args)
152
+ logger.debug "[schema_associations] #{self.name || self.from_table.classify}.#{macro} #{name.inspect}, #{argstr}"
153
+ send macro, name, *args
154
+ case
155
+ when respond_to?(:subclasses) then subclasses
156
+ end.each do |subclass|
157
+ subclass.send :_create_association, macro, name, argstr, *args
158
+ end
167
159
  end
168
- end
169
160
 
170
161
 
171
- def _determine_association_names(reference_name, referencing_name, references_name)
162
+ def _determine_association_names(reference_name, referencing_name, references_name)
172
163
 
173
- references_concise = _concise_name(references_name, referencing_name)
174
- referencing_concise = _concise_name(referencing_name, references_name)
164
+ references_concise = _concise_name(references_name, referencing_name)
165
+ referencing_concise = _concise_name(referencing_name, references_name)
175
166
 
176
- if _use_concise_name?
177
- references = references_concise
178
- referencing = referencing_concise
179
- else
180
- references = references_name
181
- referencing = referencing_name
182
- end
167
+ if _use_concise_name?
168
+ references = references_concise
169
+ referencing = referencing_concise
170
+ else
171
+ references = references_name
172
+ referencing = referencing_name
173
+ end
174
+
175
+ case reference_name
176
+ when 'parent'
177
+ belongs_to = 'parent'
178
+ has_one = 'child'
179
+ has_many = 'children'
180
+
181
+ when references_name
182
+ belongs_to = references
183
+ has_one = referencing
184
+ has_many = referencing.pluralize
185
+
186
+ when /(.*)_#{references_name}$/, /(.*)_#{references_concise}$/
187
+ label = $1
188
+ belongs_to = "#{label}_#{references}"
189
+ has_one = "#{referencing}_as_#{label}"
190
+ has_many = "#{referencing.pluralize}_as_#{label}"
191
+
192
+ when /^#{references_name}_(.*)$/, /^#{references_concise}_(.*)$/
193
+ label = $1
194
+ belongs_to = "#{references}_#{label}"
195
+ has_one = "#{referencing}_as_#{label}"
196
+ has_many = "#{referencing.pluralize}_as_#{label}"
197
+
198
+ else
199
+ belongs_to = reference_name
200
+ has_one = "#{referencing}_as_#{reference_name}"
201
+ has_many = "#{referencing.pluralize}_as_#{reference_name}"
202
+ end
183
203
 
184
- case reference_name
185
- when 'parent'
186
- belongs_to = 'parent'
187
- has_one = 'child'
188
- has_many = 'children'
189
-
190
- when references_name
191
- belongs_to = references
192
- has_one = referencing
193
- has_many = referencing.pluralize
194
-
195
- when /(.*)_#{references_name}$/, /(.*)_#{references_concise}$/
196
- label = $1
197
- belongs_to = "#{label}_#{references}"
198
- has_one = "#{referencing}_as_#{label}"
199
- has_many = "#{referencing.pluralize}_as_#{label}"
200
-
201
- when /^#{references_name}_(.*)$/, /^#{references_concise}_(.*)$/
202
- label = $1
203
- belongs_to = "#{references}_#{label}"
204
- has_one = "#{referencing}_as_#{label}"
205
- has_many = "#{referencing.pluralize}_as_#{label}"
206
-
207
- else
208
- belongs_to = reference_name
209
- has_one = "#{referencing}_as_#{reference_name}"
210
- has_many = "#{referencing.pluralize}_as_#{reference_name}"
204
+ { :belongs_to => belongs_to.to_sym, :has_one => has_one.to_sym, :has_many => has_many.to_sym }
211
205
  end
212
206
 
213
- { :belongs_to => belongs_to.to_sym, :has_one => has_one.to_sym, :has_many => has_many.to_sym }
214
- end
207
+ def _concise_name(string, other)
208
+ case
209
+ when string =~ /^#{other}_(.*)$/ then $1
210
+ when string =~ /(.*)_#{other}$/ then $1
211
+ when leader = _common_leader(string,other) then string[leader.length, string.length-leader.length]
212
+ else string
213
+ end
214
+ end
215
215
 
216
- def _concise_name(string, other) #:nodoc:
217
- case
218
- when string =~ /^#{other}_(.*)$/ then $1
219
- when string =~ /(.*)_#{other}$/ then $1
220
- when leader = _common_leader(string,other) then string[leader.length, string.length-leader.length]
221
- else string
216
+ def _common_leader(string, other)
217
+ leader = nil
218
+ other.split('_').each do |part|
219
+ test = "#{leader}#{part}_"
220
+ break unless string.start_with? test
221
+ leader = test
222
+ end
223
+ return leader
222
224
  end
223
- end
224
225
 
225
- def _common_leader(string, other) #:nodoc:
226
- leader = nil
227
- other.split('_').each do |part|
228
- test = "#{leader}#{part}_"
229
- break unless string.start_with? test
230
- leader = test
226
+ def _use_concise_name?
227
+ schema_associations_config.concise_names?
231
228
  end
232
- return leader
233
- end
234
229
 
235
- def _use_concise_name? #:nodoc:
236
- schema_associations_config.concise_names?
237
- end
230
+ def _filter_association(macro, name)
231
+ config = schema_associations_config
232
+ return false if config.only and not Array.wrap(config.only).include?(name)
233
+ return false if config.except and Array.wrap(config.except).include?(name)
234
+ return false if config.only_type and not Array.wrap(config.only_type).include?(macro)
235
+ return false if config.except_type and Array.wrap(config.except_type).include?(macro)
236
+ return true
237
+ end
238
238
 
239
- def _filter_association(macro, name) #:nodoc:
240
- config = schema_associations_config
241
- return false if config.only and not Array.wrap(config.only).include?(name)
242
- return false if config.except and Array.wrap(config.except).include?(name)
243
- return false if config.only_type and not Array.wrap(config.only_type).include?(macro)
244
- return false if config.except_type and Array.wrap(config.except_type).include?(macro)
245
- return true
246
- end
239
+ def _get_class_name(name)
240
+ name = name.dup
241
+ found = schema_associations_config.table_prefix_map.find { |table_prefix, class_prefix|
242
+ name.sub! %r[\A#{table_prefix}], ''
243
+ }
244
+ name = name.classify
245
+ name = found.last + name if found
246
+ name
247
+ end
247
248
 
248
- def _get_class_name(name) #:nodoc:
249
- name = name.dup
250
- found = schema_associations_config.table_prefix_map.find { |table_prefix, class_prefix|
251
- name.sub! %r[\A#{table_prefix}], ''
252
- }
253
- name = name.classify
254
- name = found.last + name if found
255
- name
256
- end
249
+ def _method_exists?(name)
250
+ method_defined?(name) || private_method_defined?(name) and not (name == :type && [Object, Kernel].include?(instance_method(:type).owner))
251
+ end
257
252
 
258
- def _method_exists?(name) #:nodoc:
259
- method_defined?(name) || private_method_defined?(name) and not (name == :type && [Object, Kernel].include?(instance_method(:type).owner))
260
253
  end
261
254
 
262
255
  end
@@ -1,3 +1,3 @@
1
1
  module SchemaAssociations
2
- VERSION = "1.2.4"
2
+ VERSION = "1.2.5"
3
3
  end
@@ -11,7 +11,7 @@ require 'schema_associations'
11
11
  require 'logger'
12
12
  require 'schema_dev/rspec'
13
13
 
14
- SchemaDev::Rspec::setup_db
14
+ SchemaDev::Rspec::setup
15
15
 
16
16
  Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
17
17
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: schema_associations
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 1.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ronen Barzel
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-11-15 00:00:00.000000000 Z
12
+ date: 2016-03-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: schema_plus_foreign_keys
@@ -135,7 +135,6 @@ files:
135
135
  - init.rb
136
136
  - lib/schema_associations.rb
137
137
  - lib/schema_associations/active_record/associations.rb
138
- - lib/schema_associations/railtie.rb
139
138
  - lib/schema_associations/version.rb
140
139
  - schema_associations.gemspec
141
140
  - schema_dev.yml
@@ -1,9 +0,0 @@
1
- module SchemaAssociations
2
- class Railtie < Rails::Railtie #:nodoc:
3
-
4
- initializer 'schema_associations.insert', :after => :load_config_initializers do
5
- SchemaAssociations.insert
6
- end
7
-
8
- end
9
- end