graphiti 1.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +20 -0
  6. data/.yardopts +2 -0
  7. data/Appraisals +11 -0
  8. data/CODE_OF_CONDUCT.md +49 -0
  9. data/Gemfile +12 -0
  10. data/Guardfile +32 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +75 -0
  13. data/Rakefile +15 -0
  14. data/bin/appraisal +17 -0
  15. data/bin/console +14 -0
  16. data/bin/rspec +17 -0
  17. data/bin/setup +8 -0
  18. data/gemfiles/rails_4.gemfile +17 -0
  19. data/gemfiles/rails_5.gemfile +17 -0
  20. data/graphiti.gemspec +34 -0
  21. data/lib/generators/jsonapi/resource_generator.rb +169 -0
  22. data/lib/generators/jsonapi/templates/application_resource.rb.erb +15 -0
  23. data/lib/generators/jsonapi/templates/controller.rb.erb +61 -0
  24. data/lib/generators/jsonapi/templates/create_request_spec.rb.erb +30 -0
  25. data/lib/generators/jsonapi/templates/destroy_request_spec.rb.erb +20 -0
  26. data/lib/generators/jsonapi/templates/index_request_spec.rb.erb +22 -0
  27. data/lib/generators/jsonapi/templates/resource.rb.erb +11 -0
  28. data/lib/generators/jsonapi/templates/resource_reads_spec.rb.erb +62 -0
  29. data/lib/generators/jsonapi/templates/resource_writes_spec.rb.erb +63 -0
  30. data/lib/generators/jsonapi/templates/show_request_spec.rb.erb +21 -0
  31. data/lib/generators/jsonapi/templates/update_request_spec.rb.erb +34 -0
  32. data/lib/graphiti.rb +121 -0
  33. data/lib/graphiti/adapters/abstract.rb +516 -0
  34. data/lib/graphiti/adapters/active_record.rb +6 -0
  35. data/lib/graphiti/adapters/active_record/base.rb +249 -0
  36. data/lib/graphiti/adapters/active_record/belongs_to_sideload.rb +17 -0
  37. data/lib/graphiti/adapters/active_record/has_many_sideload.rb +17 -0
  38. data/lib/graphiti/adapters/active_record/has_one_sideload.rb +17 -0
  39. data/lib/graphiti/adapters/active_record/inferrence.rb +12 -0
  40. data/lib/graphiti/adapters/active_record/many_to_many_sideload.rb +30 -0
  41. data/lib/graphiti/adapters/null.rb +236 -0
  42. data/lib/graphiti/base.rb +70 -0
  43. data/lib/graphiti/configuration.rb +21 -0
  44. data/lib/graphiti/context.rb +16 -0
  45. data/lib/graphiti/deserializer.rb +208 -0
  46. data/lib/graphiti/errors.rb +309 -0
  47. data/lib/graphiti/extensions/boolean_attribute.rb +33 -0
  48. data/lib/graphiti/extensions/extra_attribute.rb +70 -0
  49. data/lib/graphiti/extensions/temp_id.rb +26 -0
  50. data/lib/graphiti/filter_operators.rb +25 -0
  51. data/lib/graphiti/hash_renderer.rb +57 -0
  52. data/lib/graphiti/jsonapi_serializable_ext.rb +50 -0
  53. data/lib/graphiti/query.rb +251 -0
  54. data/lib/graphiti/rails.rb +28 -0
  55. data/lib/graphiti/railtie.rb +74 -0
  56. data/lib/graphiti/renderer.rb +60 -0
  57. data/lib/graphiti/resource.rb +110 -0
  58. data/lib/graphiti/resource/configuration.rb +239 -0
  59. data/lib/graphiti/resource/dsl.rb +138 -0
  60. data/lib/graphiti/resource/interface.rb +32 -0
  61. data/lib/graphiti/resource/polymorphism.rb +68 -0
  62. data/lib/graphiti/resource/sideloading.rb +102 -0
  63. data/lib/graphiti/resource_proxy.rb +127 -0
  64. data/lib/graphiti/responders.rb +19 -0
  65. data/lib/graphiti/runner.rb +25 -0
  66. data/lib/graphiti/scope.rb +98 -0
  67. data/lib/graphiti/scoping/base.rb +99 -0
  68. data/lib/graphiti/scoping/default_filter.rb +58 -0
  69. data/lib/graphiti/scoping/extra_attributes.rb +29 -0
  70. data/lib/graphiti/scoping/filter.rb +93 -0
  71. data/lib/graphiti/scoping/filterable.rb +36 -0
  72. data/lib/graphiti/scoping/paginate.rb +87 -0
  73. data/lib/graphiti/scoping/sort.rb +64 -0
  74. data/lib/graphiti/sideload.rb +281 -0
  75. data/lib/graphiti/sideload/belongs_to.rb +34 -0
  76. data/lib/graphiti/sideload/has_many.rb +16 -0
  77. data/lib/graphiti/sideload/has_one.rb +9 -0
  78. data/lib/graphiti/sideload/many_to_many.rb +24 -0
  79. data/lib/graphiti/sideload/polymorphic_belongs_to.rb +108 -0
  80. data/lib/graphiti/stats/dsl.rb +89 -0
  81. data/lib/graphiti/stats/payload.rb +49 -0
  82. data/lib/graphiti/types.rb +172 -0
  83. data/lib/graphiti/util/attribute_check.rb +88 -0
  84. data/lib/graphiti/util/field_params.rb +16 -0
  85. data/lib/graphiti/util/hash.rb +51 -0
  86. data/lib/graphiti/util/hooks.rb +33 -0
  87. data/lib/graphiti/util/include_params.rb +39 -0
  88. data/lib/graphiti/util/persistence.rb +219 -0
  89. data/lib/graphiti/util/relationship_payload.rb +64 -0
  90. data/lib/graphiti/util/serializer_attributes.rb +97 -0
  91. data/lib/graphiti/util/sideload.rb +33 -0
  92. data/lib/graphiti/util/validation_response.rb +78 -0
  93. data/lib/graphiti/version.rb +3 -0
  94. metadata +316 -0
@@ -0,0 +1,6 @@
1
+ require 'graphiti/adapters/active_record/base'
2
+ require 'graphiti/adapters/active_record/inferrence'
3
+ require 'graphiti/adapters/active_record/has_many_sideload'
4
+ require 'graphiti/adapters/active_record/belongs_to_sideload'
5
+ require 'graphiti/adapters/active_record/has_one_sideload'
6
+ require 'graphiti/adapters/active_record/many_to_many_sideload'
@@ -0,0 +1,249 @@
1
+ module Graphiti
2
+ module Adapters
3
+ module ActiveRecord
4
+ class Base < ::Graphiti::Adapters::Abstract
5
+ def filter_string_eq(scope, attribute, value, is_not: false)
6
+ column = scope.klass.arel_table[attribute]
7
+ clause = column.lower.eq_any(value.map(&:downcase))
8
+ is_not ? scope.where.not(clause) : scope.where(clause)
9
+ end
10
+
11
+ def filter_string_eql(scope, attribute, value, is_not: false)
12
+ clause = { attribute => value }
13
+ is_not ? scope.where.not(clause) : scope.where(clause)
14
+ end
15
+
16
+ def filter_string_not_eq(scope, attribute, value)
17
+ filter_string_eq(scope, attribute, value, is_not: true)
18
+ end
19
+
20
+ def filter_string_not_eql(scope, attribute, value)
21
+ filter_string_eql(scope, attribute, value, is_not: true)
22
+ end
23
+
24
+ def filter_string_prefix(scope, attribute, value, is_not: false)
25
+ column = scope.klass.arel_table[attribute]
26
+ map = value.map { |v| "#{v}%" }
27
+ clause = column.lower.matches_any(map)
28
+ is_not ? scope.where.not(clause) : scope.where(clause)
29
+ end
30
+
31
+ def filter_string_not_prefix(scope, attribute, value)
32
+ filter_string_prefix(scope, attribute, value, is_not: true)
33
+ end
34
+
35
+ def filter_string_suffix(scope, attribute, value, is_not: false)
36
+ column = scope.klass.arel_table[attribute]
37
+ map = value.map { |v| "%#{v}" }
38
+ clause = column.lower.matches_any(map)
39
+ is_not ? scope.where.not(clause) : scope.where(clause)
40
+ end
41
+
42
+ def filter_string_not_suffix(scope, attribute, value)
43
+ filter_string_suffix(scope, attribute, value, is_not: true)
44
+ end
45
+
46
+ def filter_string_match(scope, attribute, value, is_not: false)
47
+ column = scope.klass.arel_table[attribute]
48
+ map = value.map { |v| "%#{v.downcase}%" }
49
+ clause = column.lower.matches_any(map)
50
+ is_not ? scope.where.not(clause) : scope.where(clause)
51
+ end
52
+
53
+ def filter_string_not_match(scope, attribute, value)
54
+ filter_string_match(scope, attribute, value, is_not: true)
55
+ end
56
+
57
+ def filter_integer_eq(scope, attribute, value, is_not: false)
58
+ clause = { attribute => value }
59
+ is_not ? scope.where.not(clause) : scope.where(clause)
60
+ end
61
+ alias :filter_float_eq :filter_integer_eq
62
+ alias :filter_big_decimal_eq :filter_integer_eq
63
+ alias :filter_date_eq :filter_integer_eq
64
+ alias :filter_boolean_eq :filter_integer_eq
65
+
66
+ def filter_integer_not_eq(scope, attribute, value)
67
+ filter_integer_eq(scope, attribute, value, is_not: true)
68
+ end
69
+ alias :filter_float_not_eq :filter_integer_not_eq
70
+ alias :filter_big_decimal_not_eq :filter_integer_not_eq
71
+ alias :filter_date_not_eq :filter_integer_not_eq
72
+
73
+ def filter_integer_gt(scope, attribute, value)
74
+ column = scope.klass.arel_table[attribute]
75
+ scope.where(column.gt_any(value))
76
+ end
77
+ alias :filter_float_gt :filter_integer_gt
78
+ alias :filter_big_decimal_gt :filter_integer_gt
79
+ alias :filter_datetime_gt :filter_integer_gt
80
+ alias :filter_date_gt :filter_integer_gt
81
+
82
+ def filter_integer_gte(scope, attribute, value)
83
+ column = scope.klass.arel_table[attribute]
84
+ scope.where(column.gteq_any(value))
85
+ end
86
+ alias :filter_float_gte :filter_integer_gte
87
+ alias :filter_big_decimal_gte :filter_integer_gte
88
+ alias :filter_datetime_gte :filter_integer_gte
89
+ alias :filter_date_gte :filter_integer_gte
90
+
91
+ def filter_integer_lt(scope, attribute, value)
92
+ column = scope.klass.arel_table[attribute]
93
+ scope.where(column.lt_any(value))
94
+ end
95
+ alias :filter_float_lt :filter_integer_lt
96
+ alias :filter_big_decimal_lt :filter_integer_lt
97
+ alias :filter_datetime_lt :filter_integer_lt
98
+ alias :filter_date_lt :filter_integer_lt
99
+
100
+ def filter_integer_lte(scope, attribute, value)
101
+ column = scope.klass.arel_table[attribute]
102
+ scope.where(column.lteq_any(value))
103
+ end
104
+ alias :filter_float_lte :filter_integer_lte
105
+ alias :filter_big_decimal_lte :filter_integer_lte
106
+ alias :filter_date_lte :filter_integer_lte
107
+
108
+ # Ensure fractional seconds don't matter
109
+ def filter_datetime_eq(scope, attribute, value, is_not: false)
110
+ ranges = value.map { |v| (v..v+1.second-0.00000001) }
111
+ clause = { attribute => ranges }
112
+ is_not ? scope.where.not(clause) : scope.where(clause)
113
+ end
114
+
115
+ def filter_datetime_not_eq(scope, attribute, value)
116
+ filter_datetime_eq(scope, attribute, value, is_not: true)
117
+ end
118
+
119
+ def filter_datetime_lte(scope, attribute, value)
120
+ value = value.map { |v| v + 1.second-0.00000001 }
121
+ column = scope.klass.arel_table[attribute]
122
+ scope.where(column.lteq_any(value))
123
+ end
124
+
125
+ def base_scope(model)
126
+ model.all
127
+ end
128
+
129
+ # (see Adapters::Abstract#order)
130
+ def order(scope, attribute, direction)
131
+ scope.order(attribute => direction)
132
+ end
133
+
134
+ # (see Adapters::Abstract#paginate)
135
+ def paginate(scope, current_page, per_page)
136
+ scope.page(current_page).per(per_page)
137
+ end
138
+
139
+ # (see Adapters::Abstract#count)
140
+ def count(scope, attr)
141
+ if attr.to_sym == :total
142
+ scope.distinct.count
143
+ else
144
+ scope.distinct.count(attr)
145
+ end
146
+ end
147
+
148
+ # (see Adapters::Abstract#average)
149
+ def average(scope, attr)
150
+ scope.average(attr).to_f
151
+ end
152
+
153
+ # (see Adapters::Abstract#sum)
154
+ def sum(scope, attr)
155
+ scope.sum(attr)
156
+ end
157
+
158
+ # (see Adapters::Abstract#maximum)
159
+ def maximum(scope, attr)
160
+ scope.maximum(attr)
161
+ end
162
+
163
+ # (see Adapters::Abstract#minimum)
164
+ def minimum(scope, attr)
165
+ scope.minimum(attr)
166
+ end
167
+
168
+ # (see Adapters::Abstract#resolve)
169
+ def resolve(scope)
170
+ scope.to_a
171
+ end
172
+
173
+ # Run this write request within an ActiveRecord transaction
174
+ # @param [Class] model_class The ActiveRecord class we are saving
175
+ # @return Result of yield
176
+ # @see Adapters::Abstract#transaction
177
+ def transaction(model_class)
178
+ model_class.transaction do
179
+ yield
180
+ end
181
+ end
182
+
183
+ def sideloading_classes
184
+ {
185
+ has_many: HasManySideload,
186
+ has_one: HasOneSideload,
187
+ belongs_to: BelongsToSideload,
188
+ many_to_many: ManyToManySideload
189
+ }
190
+ end
191
+
192
+ def associate_all(parent, children, association_name, association_type)
193
+ association = parent.association(association_name)
194
+ association.loaded!
195
+
196
+ children.each do |child|
197
+ if association_type == :many_to_many &&
198
+ !parent.send(association_name).exists?(child.id) &&
199
+ [:create, :update].include?(Graphiti.context[:namespace])
200
+ parent.send(association_name) << child
201
+ else
202
+ target = association.instance_variable_get(:@target)
203
+ target |= [child]
204
+ association.instance_variable_set(:@target, target)
205
+ end
206
+ end
207
+ end
208
+
209
+ def associate(parent, child, association_name, association_type)
210
+ association = parent.association(association_name)
211
+ association.loaded!
212
+ association.instance_variable_set(:@target, child)
213
+ end
214
+
215
+ # When a has_and_belongs_to_many relationship, we don't have a foreign
216
+ # key that can be null'd. Instead, go through the ActiveRecord API.
217
+ # @see Adapters::Abstract#disassociate
218
+ def disassociate(parent, child, association_name, association_type)
219
+ if association_type == :many_to_many
220
+ parent.send(association_name).delete(child)
221
+ else
222
+ # Nothing to do here, happened when we merged foreign key
223
+ end
224
+ end
225
+
226
+ # (see Adapters::Abstract#create)
227
+ def create(model_class, create_params)
228
+ instance = model_class.new(create_params)
229
+ instance.save
230
+ instance
231
+ end
232
+
233
+ # (see Adapters::Abstract#update)
234
+ def update(model_class, update_params)
235
+ instance = model_class.find(update_params.delete(:id))
236
+ instance.update_attributes(update_params)
237
+ instance
238
+ end
239
+
240
+ # (see Adapters::Abstract#destroy)
241
+ def destroy(model_class, id)
242
+ instance = model_class.find(id)
243
+ instance.destroy
244
+ instance
245
+ end
246
+ end
247
+ end
248
+ end
249
+ end
@@ -0,0 +1,17 @@
1
+ module Graphiti
2
+ module Adapters
3
+ module ActiveRecord
4
+ class BelongsToSideload < Sideload::BelongsTo
5
+ include Inferrence
6
+
7
+ def default_base_scope
8
+ resource_class.model.all
9
+ end
10
+
11
+ def scope(parent_ids)
12
+ base_scope.where(primary_key => parent_ids)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Graphiti
2
+ module Adapters
3
+ module ActiveRecord # todo change
4
+ class HasManySideload < Sideload::HasMany
5
+ include Inferrence
6
+
7
+ def default_base_scope
8
+ resource_class.model.all
9
+ end
10
+
11
+ def scope(parent_ids)
12
+ base_scope.where(foreign_key => parent_ids)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Graphiti
2
+ module Adapters
3
+ module ActiveRecord
4
+ class HasOneSideload < Sideload::HasOne
5
+ include Inferrence
6
+
7
+ def default_base_scope
8
+ resource_class.model.all
9
+ end
10
+
11
+ def scope(parent_ids)
12
+ base_scope.where(foreign_key => parent_ids)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,12 @@
1
+ module Graphiti
2
+ module Adapters
3
+ module ActiveRecord
4
+ module Inferrence
5
+ def infer_foreign_key
6
+ parent_model = parent_resource_class.model
7
+ parent_model.reflections[association_name.to_s].foreign_key.to_sym
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,30 @@
1
+ module Graphiti
2
+ module Adapters
3
+ module ActiveRecord
4
+ class ManyToManySideload < Sideload::ManyToMany
5
+ def default_base_scope
6
+ resource_class.model.all
7
+ end
8
+
9
+ def through_table_name
10
+ @through_table_name ||= parent_resource_class.model
11
+ .reflections[through.to_s].klass.table_name
12
+ end
13
+
14
+ def scope(parent_ids)
15
+ base_scope
16
+ .includes(through)
17
+ .where(through_table_name => { true_foreign_key => parent_ids })
18
+ .distinct
19
+ end
20
+
21
+ def infer_foreign_key
22
+ parent_model = parent_resource_class.model
23
+ key = parent_model.reflections[name.to_s].options[:through]
24
+ value = parent_model.reflections[key.to_s].foreign_key.to_sym
25
+ { key => value }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,236 @@
1
+ module Graphiti
2
+ module Adapters
3
+ # The Null adapter is a 'pass-through' adapter. It won't modify the scope.
4
+ # Useful when your customization does not support all possible
5
+ # configuration (e.g. the service you hit does not support sorting)
6
+ class Null < Abstract
7
+ def filter_string_eq(scope, attribute, value)
8
+ scope
9
+ end
10
+
11
+ def filter_string_eql(scope, attribute, value)
12
+ scope
13
+ end
14
+
15
+ def filter_string_not_eq(scope, attribute, value)
16
+ scope
17
+ end
18
+
19
+ def filter_string_not_eql(scope, attribute, value)
20
+ scope
21
+ end
22
+
23
+ def filter_string_prefix_eq(scope, attribute, value)
24
+ scope
25
+ end
26
+
27
+ def filter_string_not_prefix_eq(scope, attribute, value)
28
+ scope
29
+ end
30
+
31
+ def filter_string_suffix_eq(scope, attribute, value)
32
+ scope
33
+ end
34
+
35
+ def filter_string_not_suffix_eq(scope, attribute, value)
36
+ scope
37
+ end
38
+
39
+ def filter_string_match_eq(scope, attribute, value)
40
+ scope
41
+ end
42
+
43
+ def filter_string_not_match_eq(scope, attribute, value)
44
+ scope
45
+ end
46
+
47
+ def filter_integer_eq(scope, attribute, value)
48
+ scope
49
+ end
50
+
51
+ def filter_integer_not_eq(scope, attribute, value)
52
+ scope
53
+ end
54
+
55
+ def filter_integer_gt(scope, attribute, value)
56
+ scope
57
+ end
58
+
59
+ def filter_integer_gte(scope, attribute, value)
60
+ scope
61
+ end
62
+
63
+ def filter_integer_lt(scope, attribute, value)
64
+ scope
65
+ end
66
+
67
+ def filter_integer_lte(scope, attribute, value)
68
+ scope
69
+ end
70
+
71
+ def filter_datetime_eq(scope, attribute, value)
72
+ scope
73
+ end
74
+
75
+ def filter_datetime_not_eq(scope, attribute, value)
76
+ scope
77
+ end
78
+
79
+ def filter_datetime_lte(scope, attribute, value)
80
+ scope
81
+ end
82
+
83
+ def filter_float_eq(scope, attribute, value)
84
+ scope
85
+ end
86
+
87
+ def filter_float_not_eq(scope, attribute, value)
88
+ scope
89
+ end
90
+
91
+ def filter_float_gt(scope, attribute, value)
92
+ scope
93
+ end
94
+
95
+ def filter_float_gte(scope, attribute, value)
96
+ scope
97
+ end
98
+
99
+ def filter_float_lt(scope, attribute, value)
100
+ scope
101
+ end
102
+
103
+ def filter_float_lte(scope, attribute, value)
104
+ scope
105
+ end
106
+
107
+ def filter_decimal_eq(scope, attribute, value)
108
+ scope
109
+ end
110
+
111
+ def filter_decimal_not_eq(scope, attribute, value)
112
+ scope
113
+ end
114
+
115
+ def filter_decimal_gt(scope, attribute, value)
116
+ scope
117
+ end
118
+
119
+ def filter_decimal_gte(scope, attribute, value)
120
+ scope
121
+ end
122
+
123
+ def filter_decimal_lt(scope, attribute, value)
124
+ scope
125
+ end
126
+
127
+ def filter_decimal_lte(scope, attribute, value)
128
+ scope
129
+ end
130
+
131
+ def filter_datetime_eq(scope, attribute, value)
132
+ scope
133
+ end
134
+
135
+ def filter_datetime_not_eq(scope, attribute, value)
136
+ scope
137
+ end
138
+
139
+ def filter_datetime_gt(scope, attribute, value)
140
+ scope
141
+ end
142
+
143
+ def filter_datetime_gte(scope, attribute, value)
144
+ scope
145
+ end
146
+
147
+ def filter_datetime_lt(scope, attribute, value)
148
+ scope
149
+ end
150
+
151
+ def filter_datetime_lte(scope, attribute, value)
152
+ scope
153
+ end
154
+
155
+ def filter_date_eq(scope, attribute, value)
156
+ scope
157
+ end
158
+
159
+ def filter_date_not_eq(scope, attribute, value)
160
+ scope
161
+ end
162
+
163
+ def filter_date_gt(scope, attribute, value)
164
+ scope
165
+ end
166
+
167
+ def filter_date_gte(scope, attribute, value)
168
+ scope
169
+ end
170
+
171
+ def filter_date_lt(scope, attribute, value)
172
+ scope
173
+ end
174
+
175
+ def filter_date_lte(scope, attribute, value)
176
+ scope
177
+ end
178
+
179
+ def filter_boolean_eq(scope, attribute, value)
180
+ scope
181
+ end
182
+
183
+ def base_scope(model)
184
+ raise 'Null adapter has no base scope!'
185
+ end
186
+
187
+ # (see Adapters::Abstract#order)
188
+ def order(scope, attribute, direction)
189
+ scope
190
+ end
191
+
192
+ # (see Adapters::Abstract#paginate)
193
+ def paginate(scope, current_page, per_page)
194
+ scope
195
+ end
196
+
197
+ # (see Adapters::Abstract#count)
198
+ def count(scope, attr)
199
+ scope
200
+ end
201
+
202
+ # (see Adapters::Abstract#average)
203
+ def average(scope, attr)
204
+ scope
205
+ end
206
+
207
+ # (see Adapters::Abstract#sum)
208
+ def sum(scope, attr)
209
+ scope
210
+ end
211
+
212
+ # (see Adapters::Abstract#sum)
213
+ def maximum(scope, attr)
214
+ scope
215
+ end
216
+
217
+ # (see Adapters::Abstract#minimum)
218
+ def minimum(scope, attr)
219
+ scope
220
+ end
221
+
222
+ # Since this is a null adapter, just yield
223
+ # @see Adapters::ActiveRecord#transaction
224
+ # @return Result of yield
225
+ # @param [Class] model_class The class we're operating on
226
+ def transaction(model_class)
227
+ yield
228
+ end
229
+
230
+ # (see Adapters::Abstract#resolve)
231
+ def resolve(scope)
232
+ scope
233
+ end
234
+ end
235
+ end
236
+ end