pluckers 1.0.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.
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