pluckers 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +51 -0
  3. data/Appraisals +22 -0
  4. data/CHANGELOG +7 -0
  5. data/CODE_OF_CONDUCT.md +49 -0
  6. data/Gemfile +4 -0
  7. data/Gemfile.lock +56 -0
  8. data/LICENSE +674 -0
  9. data/README.md +40 -0
  10. data/Rakefile +10 -0
  11. data/circle.yml +15 -0
  12. data/doc/idea.md +49 -0
  13. data/doc/usage/basics.md +46 -0
  14. data/doc/usage/extending.md +109 -0
  15. data/doc/usage/globalize.md +54 -0
  16. data/doc/usage/relationships.md +216 -0
  17. data/doc/usage/renaming.md +26 -0
  18. data/lib/pluckers/base.rb +166 -0
  19. data/lib/pluckers/features/active_record_3_2/belongs_to_reflections.rb +16 -0
  20. data/lib/pluckers/features/active_record_3_2/globalize.rb +11 -0
  21. data/lib/pluckers/features/active_record_3_2/has_and_belongs_to_many_reflections.rb +40 -0
  22. data/lib/pluckers/features/active_record_3_2/has_many_reflections.rb +16 -0
  23. data/lib/pluckers/features/active_record_3_2/has_many_through_reflections.rb +17 -0
  24. data/lib/pluckers/features/active_record_3_2/has_one_reflections.rb +17 -0
  25. data/lib/pluckers/features/active_record_3_2/has_one_through_reflections.rb +17 -0
  26. data/lib/pluckers/features/active_record_3_2/pluck.rb +26 -0
  27. data/lib/pluckers/features/active_record_3_2/renaming.rb +11 -0
  28. data/lib/pluckers/features/active_record_3_2/simple_attributes.rb +11 -0
  29. data/lib/pluckers/features/active_record_3_2.rb +10 -0
  30. data/lib/pluckers/features/active_record_4_0/belongs_to_reflections.rb +16 -0
  31. data/lib/pluckers/features/active_record_4_0/globalize.rb +11 -0
  32. data/lib/pluckers/features/active_record_4_0/has_and_belongs_to_many_reflections.rb +40 -0
  33. data/lib/pluckers/features/active_record_4_0/has_many_reflections.rb +16 -0
  34. data/lib/pluckers/features/active_record_4_0/has_many_through_reflections.rb +17 -0
  35. data/lib/pluckers/features/active_record_4_0/has_one_reflections.rb +17 -0
  36. data/lib/pluckers/features/active_record_4_0/has_one_through_reflections.rb +17 -0
  37. data/lib/pluckers/features/active_record_4_0/pluck.rb +11 -0
  38. data/lib/pluckers/features/active_record_4_0/renaming.rb +11 -0
  39. data/lib/pluckers/features/active_record_4_0/simple_attributes.rb +11 -0
  40. data/lib/pluckers/features/active_record_4_0.rb +10 -0
  41. data/lib/pluckers/features/active_record_4_1/belongs_to_reflections.rb +16 -0
  42. data/lib/pluckers/features/active_record_4_1/globalize.rb +11 -0
  43. data/lib/pluckers/features/active_record_4_1/has_and_belongs_to_many_reflections.rb +40 -0
  44. data/lib/pluckers/features/active_record_4_1/has_many_reflections.rb +16 -0
  45. data/lib/pluckers/features/active_record_4_1/has_many_through_reflections.rb +17 -0
  46. data/lib/pluckers/features/active_record_4_1/has_one_reflections.rb +17 -0
  47. data/lib/pluckers/features/active_record_4_1/has_one_through_reflections.rb +17 -0
  48. data/lib/pluckers/features/active_record_4_1/pluck.rb +11 -0
  49. data/lib/pluckers/features/active_record_4_1/renaming.rb +11 -0
  50. data/lib/pluckers/features/active_record_4_1/simple_attributes.rb +11 -0
  51. data/lib/pluckers/features/active_record_4_1.rb +10 -0
  52. data/lib/pluckers/features/active_record_4_2/belongs_to_reflections.rb +15 -0
  53. data/lib/pluckers/features/active_record_4_2/globalize.rb +11 -0
  54. data/lib/pluckers/features/active_record_4_2/has_and_belongs_to_many_reflections.rb +39 -0
  55. data/lib/pluckers/features/active_record_4_2/has_many_reflections.rb +15 -0
  56. data/lib/pluckers/features/active_record_4_2/has_many_through_reflections.rb +17 -0
  57. data/lib/pluckers/features/active_record_4_2/has_one_reflections.rb +16 -0
  58. data/lib/pluckers/features/active_record_4_2/has_one_through_reflections.rb +17 -0
  59. data/lib/pluckers/features/active_record_4_2/pluck.rb +11 -0
  60. data/lib/pluckers/features/active_record_4_2/renaming.rb +11 -0
  61. data/lib/pluckers/features/active_record_4_2/simple_attributes.rb +11 -0
  62. data/lib/pluckers/features/active_record_4_2.rb +10 -0
  63. data/lib/pluckers/features/active_record_5_0/belongs_to_reflections.rb +15 -0
  64. data/lib/pluckers/features/active_record_5_0/globalize.rb +11 -0
  65. data/lib/pluckers/features/active_record_5_0/has_and_belongs_to_many_reflections.rb +39 -0
  66. data/lib/pluckers/features/active_record_5_0/has_many_reflections.rb +15 -0
  67. data/lib/pluckers/features/active_record_5_0/has_many_through_reflections.rb +17 -0
  68. data/lib/pluckers/features/active_record_5_0/has_one_reflections.rb +16 -0
  69. data/lib/pluckers/features/active_record_5_0/has_one_through_reflections.rb +17 -0
  70. data/lib/pluckers/features/active_record_5_0/pluck.rb +11 -0
  71. data/lib/pluckers/features/active_record_5_0/renaming.rb +11 -0
  72. data/lib/pluckers/features/active_record_5_0/simple_attributes.rb +11 -0
  73. data/lib/pluckers/features/active_record_5_0.rb +10 -0
  74. data/lib/pluckers/features/base/belongs_to_reflections.rb +131 -0
  75. data/lib/pluckers/features/base/globalize.rb +116 -0
  76. data/lib/pluckers/features/base/has_and_belongs_to_many_reflections.rb +190 -0
  77. data/lib/pluckers/features/base/has_many_reflections.rb +193 -0
  78. data/lib/pluckers/features/base/has_many_through_reflections.rb +131 -0
  79. data/lib/pluckers/features/base/has_one_reflections.rb +122 -0
  80. data/lib/pluckers/features/base/has_one_through_reflections.rb +129 -0
  81. data/lib/pluckers/features/base/pluck.rb +30 -0
  82. data/lib/pluckers/features/base/renaming.rb +55 -0
  83. data/lib/pluckers/features/base/simple_attributes.rb +64 -0
  84. data/lib/pluckers/version.rb +3 -0
  85. data/lib/pluckers.rb +7 -0
  86. data/pluckers.gemspec +38 -0
  87. metadata +236 -0
@@ -0,0 +1,166 @@
1
+ active_record_version = ActiveRecord.respond_to?(:version) ? ActiveRecord.version : Gem::Version.new(ActiveRecord::VERSION::STRING)
2
+
3
+ if active_record_version > Gem::Version.new("4.2") && active_record_version < Gem::Version.new("5.0")
4
+ require_relative 'features/active_record_4_2'
5
+ elsif active_record_version > Gem::Version.new("4.1") && active_record_version < Gem::Version.new("4.2")
6
+ require_relative 'features/active_record_4_1'
7
+ elsif active_record_version > Gem::Version.new("4.0") && active_record_version < Gem::Version.new("4.1")
8
+ require_relative 'features/active_record_4_0'
9
+ elsif active_record_version > Gem::Version.new("5.0") && active_record_version < Gem::Version.new("5.1")
10
+ require_relative 'features/active_record_5_0'
11
+ elsif active_record_version > Gem::Version.new("3.2") && active_record_version < Gem::Version.new("4.0")
12
+ require_relative 'features/active_record_3_2'
13
+ else
14
+ require_relative 'features/active_record_4_2'
15
+ end
16
+
17
+ module Pluckers
18
+
19
+ ##
20
+ # This is the base class for all pluckers.
21
+ #
22
+ # It receives all the configuration in the `initialize` method and performs
23
+ # all the sql queries and hash building inside the `pluck` method.
24
+ class Base
25
+
26
+ ##
27
+ # In this attribute we store the ActiveRecord Relation we use to fetch
28
+ # information from the database
29
+ attr_reader :records
30
+
31
+ ##
32
+ # In the initialize method we recive all the options for the plucker.
33
+ #
34
+ # First, we receive an ActiveRecord Relation. It can be any ActiveRecord
35
+ # scope such as `BlogPost.all` or `BlogPost.published`. If we want to
36
+ # pluck a particular object we could pass `BlogPost.where(id: post.id )`
37
+ # so we have an ActiveRecord relation.
38
+ #
39
+ # The options hash allows us to send a lot of configuration that will be
40
+ # used by all the features and subclasses to decorate the very basic
41
+ # behaviour.
42
+ #
43
+ # Currently, the options supported by the features included in this base
44
+ # plucker are:
45
+ #
46
+ # * attributes: Names of attributes of the objects to be plucked. This
47
+ # attributes should be the names of the columns in the database. If we are
48
+ # using Globalize these attributes can also be the names of the translated
49
+ # attributes by Globalize.
50
+ #
51
+ # * attributes_with_locale: A hash when the key is a locale and the value
52
+ # is an array of attributes to pluck. As a result we will have a series of
53
+ # attributes with the name following the syntax attreibute_locale. E.g: The
54
+ # option could be { es: [:name], en: [:name, :location]} and we would obtain
55
+ # :name_es, :name_en and :location_en keys in the hash result
56
+ #
57
+ # * renames: A hash of the attributes/reflections/whatever that will be
58
+ # renamed. The key is the old name and the value is the new name.
59
+ #
60
+ # * reflections: A hash of the reflections we will pluck recursively. The
61
+ # key of this hash will be the name of the reflection and the value is
62
+ # another hash of options.
63
+ #
64
+ # - scope: You can limit the scope of the objects plucked. E.g, you
65
+ # could use Author.active instead of Author.all. Notice that .all is
66
+ # the default.
67
+ #
68
+ # - plucker: You can use a custom plucker instead of Pluckers::Base in
69
+ # case you want any specific logic. Pluckers::Base is the default one.
70
+ #
71
+ # - only_ids: In has_many reflections we can get the _ids array instead
72
+ # of an array with hashes if we pass this option as true. If we do any
73
+ # fields or plucker option will be ignored.
74
+ #
75
+ # - Any other option will be passed to the plucker, so you can send any
76
+ # other regular option such as fields, custom ones or even more
77
+ # reflections. Recursivity FTW!!
78
+ #
79
+ # The options hash can be used by subclasses to decorate all this
80
+ # behaviour and send params inside the plucker.
81
+ def initialize records, options = {}
82
+ @records = records
83
+ @options = options
84
+ @features = @options.delete(:features)
85
+ end
86
+
87
+ ##
88
+ # This method performs all the sql and hash building according to the
89
+ # received configuration.
90
+ def pluck
91
+ return [] if @records.blank?
92
+
93
+ configure_query
94
+
95
+ build_results
96
+
97
+ # And return the results
98
+ @results.values
99
+ end
100
+
101
+ ##
102
+ # In this base implementation we just reset all the query information.
103
+ # Features and subclasses must redefine this method if they are interested
104
+ # in adding some behaviour.
105
+ def configure_query
106
+ @query_to_pluck = @records
107
+ @attributes_to_pluck = [{ name: @query_to_pluck.primary_key.to_sym, sql: "\"#{@query_to_pluck.table_name}\".#{@query_to_pluck.primary_key}" }]
108
+ @results = {}
109
+ @klass_reflections = @query_to_pluck.reflections.with_indifferent_access
110
+
111
+ pluck_reflections = @options[:reflections] || {}
112
+
113
+ # Validate that all relations exists in the model
114
+ if (missing_reflections = pluck_reflections.symbolize_keys.keys - @klass_reflections.symbolize_keys.keys).any?
115
+ raise ArgumentError.new("Plucker reflections '#{missing_reflections.to_sentence}', are missing in #{@records.klass}")
116
+ end
117
+ end
118
+
119
+ ##
120
+ # In this base implementation we perform the real pluck execution.
121
+ #
122
+ # The method collects all the attributes and columns to pluck and add it
123
+ # to the results array.
124
+ def build_results
125
+
126
+ # Now we uinq the attributes
127
+ @attributes_to_pluck.uniq!{|f| f[:name] }
128
+
129
+ # Obtain both the names and SQL columns
130
+ names_to_pluck = @attributes_to_pluck.map{|f| f[:name] }
131
+ sql_to_pluck = @attributes_to_pluck.map{|f| f[:sql] }
132
+
133
+
134
+ # And perform the real ActiveRecord pluck.
135
+ pluck_records(sql_to_pluck).each_with_index do |record, index|
136
+ # After the pluck we have to create the hash for each record.
137
+
138
+ # If there's only a field we will not receive an array. But we need it
139
+ # so we built it.
140
+ record = [record] unless record.is_a? Array
141
+ # Now we zip it with the attribute names and create a hash. If we have
142
+ # have a record: [1, "Test title 1", "Test text 1"] and the
143
+ # names_to_pluck are [:id, :title, :text] we will end with {:id=>1,
144
+ # :title=>"Test title 1", :text=>"Test text 1"}
145
+ attributes_to_return = Hash[names_to_pluck.zip(record)]
146
+
147
+ # Now we store it in the results hash
148
+ @results[attributes_to_return[:id]] = attributes_to_return
149
+ end
150
+ end
151
+
152
+ include Features::Pluck
153
+
154
+ # Now we add all the base features
155
+ prepend Features::Globalize
156
+ prepend Features::SimpleAttributes
157
+ prepend Features::BelongsToReflections
158
+ prepend Features::HasManyReflections
159
+ prepend Features::HasManyThroughReflections
160
+ prepend Features::HasAndBelongsToManyReflections
161
+ prepend Features::HasOneReflections
162
+ prepend Features::HasOneThroughReflections
163
+ prepend Features::Renaming
164
+
165
+ end
166
+ end
@@ -0,0 +1,16 @@
1
+ require_relative '../base/belongs_to_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module BelongsToReflections
6
+
7
+ def active_record_belongs_to_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::AssociationReflection) &&
9
+ reflection.macro == :belongs_to
10
+ end
11
+
12
+ include Pluckers::Features::Base::BelongsToReflections
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../base/globalize'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module Globalize
6
+
7
+ include Pluckers::Features::Base::Globalize
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,40 @@
1
+ require_relative '../base/has_and_belongs_to_many_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module HasAndBelongsToManyReflections
6
+
7
+ def active_record_has_and_belongs_to_many_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::AssociationReflection) &&
9
+ (reflection.macro == :has_and_belongs_to_many)
10
+ end
11
+
12
+ def has_and_belongs_to_many_ids klass_reflection
13
+
14
+ # First, we get the the join table
15
+ join_table = Arel::Table.new(klass_reflection.options[:join_table])
16
+
17
+ # And now, the foreign_keys.
18
+ # In our example with BlogPost and Category they would be:
19
+ # model_foreign_key = blog_post_id
20
+ # related_model_foreign_key = category_id
21
+ model_foreign_key = klass_reflection.foreign_key
22
+ related_model_foreign_key = klass_reflection.association_foreign_key
23
+
24
+ # Now we query the join table so we get the two ids
25
+ ids_query = join_table.where(
26
+ join_table[model_foreign_key].in(@results.map{|_, r| r[:id] })
27
+ ).project(
28
+ join_table[related_model_foreign_key],
29
+ join_table[model_foreign_key]
30
+ )
31
+
32
+ join_results = ActiveRecord::Base.connection.execute(ids_query.to_sql)
33
+
34
+ end
35
+
36
+ include Pluckers::Features::Base::HasAndBelongsToManyReflections
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,16 @@
1
+ require_relative '../base/has_many_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module HasManyReflections
6
+
7
+ def active_record_has_many_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::AssociationReflection) &&
9
+ (reflection.macro == :has_many)
10
+ end
11
+
12
+ include Pluckers::Features::Base::HasManyReflections
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ require_relative '../base/has_many_through_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module HasManyThroughReflections
6
+
7
+ def active_record_has_many_through_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::ThroughReflection) &&
9
+ (reflection.macro == :has_many)
10
+ end
11
+
12
+ include Pluckers::Features::Base::HasManyThroughReflections
13
+
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require_relative '../base/has_one_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module HasOneReflections
6
+
7
+ def active_record_has_one_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::AssociationReflection) &&
9
+ (reflection.macro == :has_one)
10
+ end
11
+
12
+ include Pluckers::Features::Base::HasOneReflections
13
+
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require_relative '../base/has_one_through_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module HasOneThroughReflections
6
+
7
+ def active_record_has_one_through_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::ThroughReflection) &&
9
+ (reflection.macro == :has_one)
10
+ end
11
+
12
+ include Pluckers::Features::Base::HasOneThroughReflections
13
+
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ module Pluckers
2
+ module Features
3
+ module Pluck
4
+
5
+ ##
6
+ # In ActiveRecord 3.2 pluck only accepts one column. We have to go
7
+ # around it and not actually use the pluck method.
8
+ #
9
+ # Idea based on http://meltingice.net/2013/06/11/pluck-multiple-columns-rails/
10
+ def pluck_records(*fields_to_pluck)
11
+ records_clone = @records.clone
12
+ records_clone.select_values = fields_to_pluck
13
+ @records.connection.select_all(records_clone.arel).map do |attributes|
14
+ initialized_attributes = @records.klass.initialize_attributes(attributes)
15
+ attributes.each do |key, attribute|
16
+ attributes[key] = @records.klass.type_cast_attribute(key, initialized_attributes)
17
+ end
18
+ end
19
+ end
20
+
21
+ def all_method
22
+ :scoped
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../base/renaming'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module Renaming
6
+
7
+ include Pluckers::Features::Base::Renaming
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../base/simple_attributes'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module SimpleAttributes
6
+
7
+ include Pluckers::Features::Base::SimpleAttributes
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ require_relative 'active_record_3_2/simple_attributes'
2
+ require_relative 'active_record_3_2/belongs_to_reflections'
3
+ require_relative 'active_record_3_2/has_many_reflections'
4
+ require_relative 'active_record_3_2/has_many_through_reflections'
5
+ require_relative 'active_record_3_2/has_and_belongs_to_many_reflections'
6
+ require_relative 'active_record_3_2/has_one_reflections'
7
+ require_relative 'active_record_3_2/has_one_through_reflections'
8
+ require_relative 'active_record_3_2/renaming'
9
+ require_relative 'active_record_3_2/globalize'
10
+ require_relative 'active_record_3_2/pluck'
@@ -0,0 +1,16 @@
1
+ require_relative '../base/belongs_to_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module BelongsToReflections
6
+
7
+ def active_record_belongs_to_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::AssociationReflection) &&
9
+ reflection.macro == :belongs_to
10
+ end
11
+
12
+ include Pluckers::Features::Base::BelongsToReflections
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../base/globalize'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module Globalize
6
+
7
+ include Pluckers::Features::Base::Globalize
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,40 @@
1
+ require_relative '../base/has_and_belongs_to_many_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module HasAndBelongsToManyReflections
6
+
7
+ def active_record_has_and_belongs_to_many_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::AssociationReflection) &&
9
+ (reflection.macro == :has_and_belongs_to_many)
10
+ end
11
+
12
+ def has_and_belongs_to_many_ids klass_reflection
13
+
14
+ # First, we get the the join table
15
+ join_table = Arel::Table.new(klass_reflection.join_table)
16
+
17
+ # And now, the foreign_keys.
18
+ # In our example with BlogPost and Category they would be:
19
+ # model_foreign_key = blog_post_id
20
+ # related_model_foreign_key = category_id
21
+ model_foreign_key = klass_reflection.foreign_key
22
+ related_model_foreign_key = klass_reflection.association_foreign_key
23
+
24
+ # Now we query the join table so we get the two ids
25
+ ids_query = join_table.where(
26
+ join_table[model_foreign_key].in(@results.map{|_, r| r[:id] })
27
+ ).project(
28
+ join_table[related_model_foreign_key],
29
+ join_table[model_foreign_key]
30
+ )
31
+
32
+ join_results = ActiveRecord::Base.connection.execute(ids_query.to_sql)
33
+
34
+ end
35
+
36
+ include Pluckers::Features::Base::HasAndBelongsToManyReflections
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,16 @@
1
+ require_relative '../base/has_many_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module HasManyReflections
6
+
7
+ def active_record_has_many_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::AssociationReflection) &&
9
+ (reflection.macro == :has_many)
10
+ end
11
+
12
+ include Pluckers::Features::Base::HasManyReflections
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ require_relative '../base/has_many_through_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module HasManyThroughReflections
6
+
7
+ def active_record_has_many_through_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::ThroughReflection) &&
9
+ (reflection.macro == :has_many)
10
+ end
11
+
12
+ include Pluckers::Features::Base::HasManyThroughReflections
13
+
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require_relative '../base/has_one_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module HasOneReflections
6
+
7
+ def active_record_has_one_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::AssociationReflection) &&
9
+ (reflection.macro == :has_one)
10
+ end
11
+
12
+ include Pluckers::Features::Base::HasOneReflections
13
+
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require_relative '../base/has_one_through_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module HasOneThroughReflections
6
+
7
+ def active_record_has_one_through_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::ThroughReflection) &&
9
+ (reflection.macro == :has_one)
10
+ end
11
+
12
+ include Pluckers::Features::Base::HasOneThroughReflections
13
+
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../base/pluck'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module Pluck
6
+
7
+ include Pluckers::Features::Base::Pluck
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../base/renaming'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module Renaming
6
+
7
+ include Pluckers::Features::Base::Renaming
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../base/simple_attributes'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module SimpleAttributes
6
+
7
+ include Pluckers::Features::Base::SimpleAttributes
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ require_relative 'active_record_4_0/simple_attributes'
2
+ require_relative 'active_record_4_0/belongs_to_reflections'
3
+ require_relative 'active_record_4_0/has_many_reflections'
4
+ require_relative 'active_record_4_0/has_many_through_reflections'
5
+ require_relative 'active_record_4_0/has_and_belongs_to_many_reflections'
6
+ require_relative 'active_record_4_0/has_one_reflections'
7
+ require_relative 'active_record_4_0/has_one_through_reflections'
8
+ require_relative 'active_record_4_0/renaming'
9
+ require_relative 'active_record_4_0/globalize'
10
+ require_relative 'active_record_4_0/pluck'
@@ -0,0 +1,16 @@
1
+ require_relative '../base/belongs_to_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module BelongsToReflections
6
+
7
+ def active_record_belongs_to_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::AssociationReflection) &&
9
+ reflection.macro == :belongs_to
10
+ end
11
+
12
+ include Pluckers::Features::Base::BelongsToReflections
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../base/globalize'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module Globalize
6
+
7
+ include Pluckers::Features::Base::Globalize
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,40 @@
1
+ require_relative '../base/has_and_belongs_to_many_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module HasAndBelongsToManyReflections
6
+
7
+ def active_record_has_and_belongs_to_many_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::AssociationReflection) &&
9
+ (reflection.macro == :has_and_belongs_to_many)
10
+ end
11
+
12
+ def has_and_belongs_to_many_ids klass_reflection
13
+
14
+ # First, we get the the join table
15
+ join_table = Arel::Table.new(klass_reflection.join_table)
16
+
17
+ # And now, the foreign_keys.
18
+ # In our example with BlogPost and Category they would be:
19
+ # model_foreign_key = blog_post_id
20
+ # related_model_foreign_key = category_id
21
+ model_foreign_key = klass_reflection.foreign_key
22
+ related_model_foreign_key = klass_reflection.association_foreign_key
23
+
24
+ # Now we query the join table so we get the two ids
25
+ ids_query = join_table.where(
26
+ join_table[model_foreign_key].in(@results.map{|_, r| r[:id] })
27
+ ).project(
28
+ join_table[related_model_foreign_key],
29
+ join_table[model_foreign_key]
30
+ )
31
+
32
+ join_results = ActiveRecord::Base.connection.execute(ids_query.to_sql)
33
+
34
+ end
35
+
36
+ include Pluckers::Features::Base::HasAndBelongsToManyReflections
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,16 @@
1
+ require_relative '../base/has_many_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module HasManyReflections
6
+
7
+ def active_record_has_many_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::AssociationReflection) &&
9
+ (reflection.macro == :has_many)
10
+ end
11
+
12
+ include Pluckers::Features::Base::HasManyReflections
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ require_relative '../base/has_many_through_reflections'
2
+
3
+ module Pluckers
4
+ module Features
5
+ module HasManyThroughReflections
6
+
7
+ def active_record_has_many_through_reflection? reflection
8
+ reflection.is_a?(ActiveRecord::Reflection::ThroughReflection) &&
9
+ (reflection.macro == :has_many)
10
+ end
11
+
12
+ include Pluckers::Features::Base::HasManyThroughReflections
13
+
14
+
15
+ end
16
+ end
17
+ end