ardm 0.0.1 → 0.1.0
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 +5 -13
- data/Gemfile +1 -2
- data/LICENSE +2 -2
- data/README.md +72 -16
- data/ardm.gemspec +1 -0
- data/lib/ardm.rb +2 -1
- data/lib/ardm/active_record.rb +8 -1
- data/lib/ardm/active_record/associations.rb +33 -4
- data/lib/ardm/active_record/base.rb +2 -0
- data/lib/ardm/active_record/collection.rb +5 -0
- data/lib/ardm/active_record/data_mapper_constant.rb +1 -0
- data/lib/ardm/active_record/data_mapper_constant_proxy.rb +24 -0
- data/lib/ardm/active_record/finalize.rb +18 -0
- data/lib/ardm/active_record/predicate_builder/array_handler.rb +10 -16
- data/lib/ardm/active_record/predicate_builder/rails3.rb +42 -15
- data/lib/ardm/active_record/predicate_builder/rails4.rb +39 -13
- data/lib/ardm/active_record/property.rb +24 -12
- data/lib/ardm/active_record/query.rb +9 -18
- data/lib/ardm/active_record/record.rb +54 -11
- data/lib/ardm/active_record/relation.rb +36 -6
- data/lib/ardm/active_record/repository.rb +6 -2
- data/lib/ardm/data_mapper.rb +2 -0
- data/lib/ardm/data_mapper/record.rb +3 -9
- data/lib/ardm/version.rb +1 -1
- data/spec/ardm/datamapper_constants_spec.rb +31 -0
- data/spec/fixtures/article.rb +2 -0
- data/spec/integration/api_key_spec.rb +3 -3
- data/spec/integration/bcrypt_hash_spec.rb +7 -7
- data/spec/integration/comma_separated_list_spec.rb +11 -11
- data/spec/integration/dirty_minder_spec.rb +23 -39
- data/spec/integration/enum_spec.rb +11 -11
- data/spec/integration/epoch_time_spec.rb +6 -6
- data/spec/integration/file_path_spec.rb +23 -23
- data/spec/integration/flag_spec.rb +11 -13
- data/spec/integration/ip_address_spec.rb +15 -15
- data/spec/integration/json_spec.rb +7 -7
- data/spec/integration/slug_spec.rb +6 -6
- data/spec/integration/uri_spec.rb +11 -11
- data/spec/integration/uuid_spec.rb +16 -16
- data/spec/integration/yaml_spec.rb +8 -8
- data/spec/public/model_spec.rb +193 -0
- data/spec/public/property/binary_spec.rb +4 -4
- data/spec/public/property/boolean_spec.rb +3 -3
- data/spec/public/property/class_spec.rb +2 -2
- data/spec/public/property/date_spec.rb +2 -2
- data/spec/public/property/date_time_spec.rb +2 -2
- data/spec/public/property/decimal_spec.rb +2 -2
- data/spec/public/property/discriminator_spec.rb +21 -20
- data/spec/public/property/float_spec.rb +2 -2
- data/spec/public/property/integer_spec.rb +2 -2
- data/spec/public/property/object_spec.rb +14 -13
- data/spec/public/property/serial_spec.rb +2 -2
- data/spec/public/property/string_spec.rb +2 -2
- data/spec/public/property/text_spec.rb +2 -2
- data/spec/public/property/time_spec.rb +2 -2
- data/spec/public/property_spec.rb +44 -48
- data/spec/public/resource_spec.rb +278 -0
- data/spec/schema.rb +33 -4
- data/spec/semipublic/property/boolean_spec.rb +5 -5
- data/spec/semipublic/property/class_spec.rb +3 -3
- data/spec/semipublic/property/date_spec.rb +8 -8
- data/spec/semipublic/property/date_time_spec.rb +9 -9
- data/spec/semipublic/property/decimal_spec.rb +16 -16
- data/spec/semipublic/property/float_spec.rb +16 -16
- data/spec/semipublic/property/integer_spec.rb +16 -16
- data/spec/semipublic/property/lookup_spec.rb +4 -4
- data/spec/semipublic/property/text_spec.rb +2 -2
- data/spec/semipublic/property/time_spec.rb +10 -10
- data/spec/semipublic/property_spec.rb +4 -4
- data/spec/shared/finder_shared_spec.rb +1151 -0
- data/spec/shared/flags_shared_spec.rb +6 -6
- data/spec/shared/identity_function_group.rb +1 -1
- data/spec/shared/public_property_spec.rb +26 -25
- data/spec/shared/resource_spec.rb +1218 -0
- data/spec/shared/semipublic_property_spec.rb +23 -22
- data/spec/spec_helper.rb +17 -0
- data/spec/unit/bcrypt_hash_spec.rb +15 -15
- data/spec/unit/csv_spec.rb +11 -11
- data/spec/unit/dirty_minder_spec.rb +3 -5
- data/spec/unit/enum_spec.rb +17 -17
- data/spec/unit/epoch_time_spec.rb +8 -8
- data/spec/unit/file_path_spec.rb +9 -9
- data/spec/unit/flag_spec.rb +9 -9
- data/spec/unit/ip_address_spec.rb +9 -9
- data/spec/unit/json_spec.rb +11 -11
- data/spec/unit/paranoid_boolean_spec.rb +19 -17
- data/spec/unit/paranoid_datetime_spec.rb +21 -19
- data/spec/unit/regexp_spec.rb +4 -4
- data/spec/unit/uri_spec.rb +8 -8
- data/spec/unit/yaml_spec.rb +9 -9
- metadata +35 -27
- data/lib/ardm/active_record/not_found.rb +0 -7
- data/lib/ardm/data_mapper/not_found.rb +0 -5
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
YmZlNzI5MzMzMjdlZDQwYjExZjcxYjZiNjA5YTkyZTBmM2QxOGZlMQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 866545bbe125ccbada17fad21e0fcc1b3ff15fa0
|
4
|
+
data.tar.gz: 6d5ebf8a7cf672ec89125d8bace07470229ecd33
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
MTA5OWQ2ODUzMmRhN2M3ZWM2MWUyODkxOWU0ZmU2OTFjZGIwN2Y1ZmVkZGNh
|
11
|
-
Nzk3M2I3NzhmOTNiZDcxNjVkY2E2ZWE2MTY1MmQ1NGIwMjc3OTI=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NzcxYzU2NDRiMjU5NjVkYTVhNjNiZGEyMGRhYWVlYmYxOTc2ZDBhN2Q0YjE2
|
14
|
-
NzI3MTYzNDg5ODRjZTY1Y2U1N2JiYmMzZDdmNDlhYTBkYmZiYTJiMmFjMjk1
|
15
|
-
MWUzMmExYjQ5NGQxN2IxZjc2ZTIwZGU0ZGIzNzE4ZGM5Y2JiYTg=
|
6
|
+
metadata.gz: 60564ee06c22d8e54564a87ec294896b74f6753f2ce004cc615f325ef8521025eeaf821d7fb3e359de45b9a9ef3124b4ae663ebe6b26849b93ae494d121b8346
|
7
|
+
data.tar.gz: 7403cb0bbd7f8b636b572267977a9302fa4e35c4027bcede569b77f49645027df75e4ab1db2658e3976fbf0e773fa5b6748f169d9c82774cec728dd3c9dee572
|
data/Gemfile
CHANGED
data/LICENSE
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
Adaptation of dm-core to run atop Active Record Copyright (c) 2013 Engine Yard
|
2
|
+
dm-types and dm-core source code Copyright (c) 2011 Sam Smoot, Dan Kubb
|
3
3
|
|
4
4
|
Permission is hereby granted, free of charge, to any person obtaining
|
5
5
|
a copy of this software and associated documentation files (the
|
data/README.md
CHANGED
@@ -2,32 +2,44 @@
|
|
2
2
|
|
3
3
|
ActiveRecord plugin to provide a smooth migration from DataMapper to ActiveRecord.
|
4
4
|
|
5
|
+
This code is currently in development and not feature complete.
|
6
|
+
Your code is probably different than mine, so please contribute to bridge
|
7
|
+
the gap from DataMapper to ActiveRecord and Rails 4.
|
8
|
+
|
5
9
|
## Why
|
6
10
|
|
7
11
|
Ardm is intended for applications running Rails with DataMapper 1.2 who need
|
8
|
-
to migrate to ActiveRecord
|
9
|
-
move to ActiveRecord.
|
12
|
+
to migrate to ActiveRecord so they can move forward onto Rails 4.
|
13
|
+
Lets examine some of the reasons why you might move to ActiveRecord.
|
10
14
|
|
11
15
|
* DataMapper is no longer under development. Ruby Object Mapper (ROM) is the
|
12
|
-
|
13
|
-
is a completely new codebase and very few of the idioms transfer.
|
16
|
+
implicit replacement for DataMapper, but it's not a supported migration.
|
17
|
+
ROM is a completely new codebase and very few of the idioms transfer.
|
14
18
|
* DataMapper produces inefficient queries. Includes, joins, and subqueries are
|
15
19
|
either not supported or incorrect. Enabling subqueries in DM speeds up queries
|
16
20
|
but causes other subtle query problems than can produce bad SQL that may
|
17
21
|
select incorrect records.
|
18
|
-
* DataMapper cannot currently run on
|
22
|
+
* DataMapper cannot currently run on Rails 4. Someone may take the initiative to
|
19
23
|
upgrade DataMapper to work on Rails4, but I think you're much better off
|
20
24
|
moving to ActiveRecord.
|
21
25
|
* Arel is awesome. ActiveRecord and Arel together is quite nice. With the added
|
22
|
-
support properties and the advances in
|
23
|
-
* ActiveRecord is used in more applications, better tested, and more
|
26
|
+
support properties and the advances in Rails 4, I think this upgrade is a must.
|
27
|
+
* ActiveRecord is used in more applications, is better tested, and is more
|
28
|
+
performant than DataMapper.
|
24
29
|
|
25
30
|
## Installation
|
26
31
|
|
27
|
-
|
32
|
+
require 'ardm'
|
33
|
+
|
34
|
+
Run your project using the ORM environment variable.
|
35
|
+
|
36
|
+
ORM=activerecord bundle exec rake spec
|
37
|
+
ORM=datamapper bundle exec rake spec
|
38
|
+
|
39
|
+
## Incremental migration from DataMapper to ActiveRecord
|
28
40
|
|
29
|
-
ActiveRecord requires your models to inherit from ActiveRecord::Base,
|
30
|
-
it difficult to approach
|
41
|
+
ActiveRecord requires your models to inherit from ActiveRecord::Base, which makes
|
42
|
+
it difficult to approach this migration incrementally. All or nothing is a scary
|
31
43
|
way to switch ORMs. To solve this, Ardm supplies Ardm::Record.
|
32
44
|
|
33
45
|
Ardm::Record will be the new base class. You'll need to search and replace
|
@@ -50,16 +62,60 @@ Example:
|
|
50
62
|
|
51
63
|
With this new base clase you can switch between ActiveRecord and DataMapper
|
52
64
|
by flipping a swith in your application. This approach allows you to continue
|
53
|
-
developing your application in DataMapper while you work on
|
65
|
+
developing your application in DataMapper while you work on removing all
|
54
66
|
the "datamapper-isms" from your code. This library attempts to take care of
|
55
67
|
most DataMapper features, but there are probably tons of small variations
|
56
68
|
that are not accounted for.
|
57
69
|
|
58
|
-
##
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
70
|
+
## General Strategy
|
71
|
+
|
72
|
+
This is a complex thing to approach. I'm hoping this project can make this move
|
73
|
+
into a repeatable strategy rather than everyone needing to create their own
|
74
|
+
unique solution.
|
75
|
+
|
76
|
+
1. Get the application running with Ardm installed. Don't even think about
|
77
|
+
ActiveRecord until you have Ardm working in DataMapper mode and you can
|
78
|
+
deploy your application normally with ardm installed.
|
79
|
+
2. Start to remove references to `DataMapper` by using the conversions
|
80
|
+
mentioned below. The idea is to remove the `DataMapper` constant completely
|
81
|
+
so you can run without `dm-core` when in ActiveRecord mode.
|
82
|
+
3. Once your application runs smoothly in DataMapper mode with all the
|
83
|
+
constants using Ardm, try to get the application to start the test run
|
84
|
+
in ActiveRecord mode. This will probably require a bunch of hunting through
|
85
|
+
the application for datamapper-isms that are not accounted for in Ardm.
|
86
|
+
**Please help by contributing these fixes back to Ardm!**
|
87
|
+
4. Make all your tests pass in ActiveRecord and DataMapper mode. This is an
|
88
|
+
ideal. You could decide that you're close enough and start sacrificing
|
89
|
+
DataMapper specific code for ActiveRecord code. You can branch around
|
90
|
+
picky code with the `Ardme.activerecord?` and `Ardm.datamapper?` helpers.
|
91
|
+
|
92
|
+
## Conversions
|
93
|
+
|
94
|
+
Things that access DataMapper directly can be replaced with Ardm invocations:
|
95
|
+
|
96
|
+
DataMapper.finalize => Ardm::Record.finalize (no-op in AR mode)
|
97
|
+
DataMapper.repository => Ardm::Record.repository
|
98
|
+
DataMapper.logger => Ardm::Record.logger
|
99
|
+
|
100
|
+
DataMapper::ObjectNotFoundError => Ardm::Record::NotFound
|
101
|
+
ActiveRecord::RecordNotFound => Ardm::Record::NotFound
|
102
|
+
|
103
|
+
DataMapper::Property => Ardm::Property
|
104
|
+
DataMapper::Property::String => Ardm::Property::String
|
105
|
+
|
106
|
+
This pattern follows for most DataMapper module methods. When running in
|
107
|
+
DataMapper mode, these simply forward. In ActiveRecord mode, they provide
|
108
|
+
adapters for accessing the same data through ActiveRecord.
|
109
|
+
|
110
|
+
If you run into code that is particularly difficult to convert, you can
|
111
|
+
duplicate the code and write a different version for each ORM:
|
112
|
+
|
113
|
+
if Ardm.activerecord?
|
114
|
+
Thing.where(Thing.arel_table[:field].matches('something'))
|
115
|
+
else
|
116
|
+
# This is just an example. This should actually work fine in Ardm.
|
117
|
+
Thing.all(:field.like => 'something')
|
118
|
+
end
|
63
119
|
|
64
120
|
## Copyright
|
65
121
|
|
data/ardm.gemspec
CHANGED
@@ -7,6 +7,7 @@ Gem::Specification.new do |gem|
|
|
7
7
|
gem.summary = "ActiveRecord plugin to provide a smooth migration from DataMapper to ActiveRecord"
|
8
8
|
gem.description = gem.summary
|
9
9
|
gem.homepage = "http://github.com/engineyard/ardm"
|
10
|
+
gem.license = "MIT"
|
10
11
|
|
11
12
|
gem.files = `git ls-files`.split("\n")
|
12
13
|
gem.test_files = `git ls-files -- {spec}/*`.split("\n")
|
data/lib/ardm.rb
CHANGED
data/lib/ardm/active_record.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
puts __FILE__
|
2
1
|
require 'ardm'
|
3
2
|
|
4
3
|
# only load support libs in active record mode (dm will supply its own libs)
|
@@ -29,11 +28,19 @@ require 'active_record/relation'
|
|
29
28
|
|
30
29
|
require 'ardm/active_record/record'
|
31
30
|
require 'ardm/active_record/relation'
|
31
|
+
require 'ardm/active_record/data_mapper_constant_proxy'
|
32
32
|
|
33
33
|
module Ardm
|
34
34
|
Record = Ardm::ActiveRecord::Record
|
35
|
+
SaveFailureError = ::ActiveRecord::RecordNotSaved
|
36
|
+
RecordNotFound = ::ActiveRecord::RecordNotFound
|
37
|
+
|
38
|
+
def self.define_datamapper_constant!
|
39
|
+
require 'ardm/active_record/data_mapper_constant'
|
40
|
+
end
|
35
41
|
end
|
36
42
|
|
43
|
+
|
37
44
|
#::ActiveRecord::Base.class_eval do
|
38
45
|
# include Ardm::ActiveRecord::Base
|
39
46
|
#end
|
@@ -40,13 +40,42 @@ module Ardm
|
|
40
40
|
end
|
41
41
|
|
42
42
|
module ClassMethods
|
43
|
-
|
43
|
+
|
44
|
+
def dump_associations_hash(options)
|
45
|
+
options.inject({}) do |new_attrs, (key, value)|
|
46
|
+
if reflection = reflect_on_association(key.to_sym)
|
47
|
+
if value.is_a?(ActiveRecord::Base)
|
48
|
+
new_attrs[reflection.foreign_key] = value.id
|
49
|
+
if reflection.respond_to?(:polymorphic?) && reflection.polymorphic?
|
50
|
+
new_attrs[reflection.foreign_type] = value.class.base_class
|
51
|
+
end
|
52
|
+
else
|
53
|
+
new_attrs[reflection.foreign_key] = value
|
54
|
+
end
|
55
|
+
else
|
56
|
+
new_attrs[key] = value
|
57
|
+
end
|
58
|
+
new_attrs
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def belongs_to(field, *args)
|
63
|
+
options = args.shift || {}
|
64
|
+
|
65
|
+
if String === options || Class === options # belongs_to :name, 'Class', options: 'here'
|
66
|
+
options = (args.last || {}).merge(:model => options.to_s)
|
67
|
+
end
|
68
|
+
|
69
|
+
unless Hash === options
|
70
|
+
raise ArgumentError, "bad belongs_to #{field} options format #{options.inspect}"
|
71
|
+
end
|
72
|
+
|
44
73
|
options.delete(:default)
|
45
74
|
options.delete(:required)
|
46
75
|
opts = Ardm::ActiveRecord::Associations.convert_options(self, options)
|
47
76
|
super field, opts
|
48
77
|
assoc = reflect_on_association(field)
|
49
|
-
property assoc.foreign_key,
|
78
|
+
property assoc.foreign_key, assoc.klass.key.first.class
|
50
79
|
nil
|
51
80
|
end
|
52
81
|
|
@@ -57,8 +86,8 @@ module Ardm
|
|
57
86
|
def has(count, name, *args)
|
58
87
|
options = args.shift || {}
|
59
88
|
|
60
|
-
if String === options # has n, :name, 'Class', options: 'here'
|
61
|
-
options = (args.last || {}).merge(:model => options)
|
89
|
+
if String === options || Class === options # has n, :name, 'Class', options: 'here'
|
90
|
+
options = (args.last || {}).merge(:model => options.to_s)
|
62
91
|
end
|
63
92
|
|
64
93
|
unless Hash === options
|
@@ -2,6 +2,7 @@ require 'active_support/concern'
|
|
2
2
|
|
3
3
|
require 'ardm/active_record/associations'
|
4
4
|
require 'ardm/active_record/dirty'
|
5
|
+
require 'ardm/active_record/finalize'
|
5
6
|
require 'ardm/active_record/hooks'
|
6
7
|
require 'ardm/active_record/is'
|
7
8
|
require 'ardm/active_record/inheritance'
|
@@ -35,6 +36,7 @@ module Ardm
|
|
35
36
|
extend ActiveSupport::Concern
|
36
37
|
|
37
38
|
include Ardm::ActiveRecord::Associations
|
39
|
+
include Ardm::ActiveRecord::Finalize
|
38
40
|
include Ardm::ActiveRecord::Hooks
|
39
41
|
include Ardm::ActiveRecord::Dirty
|
40
42
|
include Ardm::ActiveRecord::Is
|
@@ -0,0 +1 @@
|
|
1
|
+
::DataMapper = Ardm::ActiveRecord::DataMapperConstantProxy
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Ardm
|
2
|
+
module ActiveRecord
|
3
|
+
module DataMapperConstantProxy
|
4
|
+
|
5
|
+
class << self
|
6
|
+
extend Forwardable
|
7
|
+
def_delegators 'Ardm::Record',
|
8
|
+
:finalize,
|
9
|
+
:repository,
|
10
|
+
:logger,
|
11
|
+
:logger=
|
12
|
+
end
|
13
|
+
|
14
|
+
module Resource
|
15
|
+
end
|
16
|
+
|
17
|
+
ObjectNotFoundError = ::ActiveRecord::RecordNotFound
|
18
|
+
SaveFailureError = ::ActiveRecord::RecordNotSaved
|
19
|
+
|
20
|
+
Property = Ardm::Property
|
21
|
+
Collection = Ardm::Collection
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Ardm
|
2
|
+
module ActiveRecord
|
3
|
+
module Finalize
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
class_attribute :on_finalize
|
8
|
+
self.on_finalize = []
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def finalize
|
13
|
+
on_finalize.each { |f| f.call }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -3,27 +3,21 @@ module Ardm
|
|
3
3
|
module PredicateBuilder
|
4
4
|
class ArrayHandler # :nodoc:
|
5
5
|
def call(attribute, value)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
values_predicate = if values.include?(nil)
|
10
|
-
values = values.compact
|
11
|
-
|
12
|
-
case values.length
|
13
|
-
when 0
|
6
|
+
if value.include?(nil)
|
7
|
+
values = value.compact
|
8
|
+
if values.length == 0
|
14
9
|
attribute.eq(nil)
|
15
|
-
when 1
|
16
|
-
attribute.eq(values.first).or(attribute.eq(nil))
|
17
10
|
else
|
18
|
-
attribute
|
11
|
+
call(attribute, values).or(attribute.eq(nil))
|
19
12
|
end
|
20
13
|
else
|
21
|
-
|
22
|
-
|
14
|
+
values = value.map { |x| x.is_a?(::ActiveRecord::Base) ? x.id : x }
|
15
|
+
ranges, values = values.partition { |v| v.is_a?(::Range) }
|
23
16
|
|
24
|
-
|
25
|
-
|
26
|
-
|
17
|
+
array_predicates = ranges.map { |range| attribute.in(range) }
|
18
|
+
array_predicates << attribute.in(values)
|
19
|
+
array_predicates.inject { |composite, predicate| composite.or(predicate) }
|
20
|
+
end
|
27
21
|
end
|
28
22
|
end
|
29
23
|
end
|
@@ -40,7 +40,9 @@ module Ardm
|
|
40
40
|
|
41
41
|
def build_from_hash(klass, attributes, default_table)
|
42
42
|
queries = []
|
43
|
-
|
43
|
+
# HAX (this method is added to the attributes hash by expand_hash_conditions_for_aggregates
|
44
|
+
# Rails 3 calls build_form_hash with the first arg that is not the klass.
|
45
|
+
klass = attributes.klass
|
44
46
|
|
45
47
|
attributes.each do |column, value|
|
46
48
|
table = default_table
|
@@ -85,26 +87,51 @@ module Ardm
|
|
85
87
|
end
|
86
88
|
|
87
89
|
def expand(klass, table, column, value)
|
88
|
-
|
90
|
+
if klass && association = klass.reflect_on_association(column.to_sym)
|
91
|
+
expand_association(association, table, column, value)
|
92
|
+
else
|
93
|
+
[build(table[column], value)]
|
94
|
+
end
|
95
|
+
end
|
89
96
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
97
|
+
# Find the foreign key when using queries such as:
|
98
|
+
# Post.where(author: author)
|
99
|
+
#
|
100
|
+
# For polymorphic relationships, find the foreign key and type:
|
101
|
+
# PriceEstimate.where(estimate_of: treasure)
|
102
|
+
#
|
103
|
+
# Attempt to build a query that makes sense for an association name
|
104
|
+
# in the query, but if we can't generate a propery query, fallback
|
105
|
+
# to using the original key we received.
|
106
|
+
def expand_association(association, table, column, value)
|
107
|
+
queries = []
|
108
|
+
case association.macro
|
109
|
+
when :belongs_to
|
110
|
+
if association.polymorphic? && base_class = polymorphic_base_class_from_value(value)
|
111
|
+
queries << build(table[association.foreign_type], base_class)
|
99
112
|
end
|
113
|
+
queries << build(table[association.foreign_key], value)
|
114
|
+
when :has_many, :has_one
|
115
|
+
table = Arel::Table.new(association.klass.table_name, table.engine)
|
116
|
+
queries << build(table[association.klass.primary_key], value)
|
117
|
+
else
|
118
|
+
queries << build(table[column], value)
|
100
119
|
end
|
101
|
-
|
102
|
-
#puts "expand(#{klass.name}, #{column.inspect}, #{value.inspect})"
|
103
|
-
|
104
|
-
queries << build(table[column], value)
|
105
120
|
queries
|
106
121
|
end
|
107
122
|
|
123
|
+
def polymorphic_base_class_from_value(value)
|
124
|
+
case value
|
125
|
+
when Relation
|
126
|
+
value.klass.base_class
|
127
|
+
when Array
|
128
|
+
val = value.compact.first
|
129
|
+
val.class.base_class if val.is_a?(Base)
|
130
|
+
when Base
|
131
|
+
value.class.base_class
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
108
135
|
def references(attributes)
|
109
136
|
attributes.map do |key, value|
|
110
137
|
if value.is_a?(Hash)
|