Class: Graphiti::Adapters::ActiveRecord

Inherits:
Abstract show all
Defined in:
lib/graphiti/adapters/active_record.rb

Defined Under Namespace

Modules: Inferrence Classes: BelongsToSideload, HasManySideload, HasOneSideload, ManyToManySideload

Instance Attribute Summary

Attributes inherited from Abstract

#resource

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Abstract

#assign_attributes, #belongs_to_many_filter, #build, default_operators, #initialize, numerical_operators

Constructor Details

This class inherits a constructor from Graphiti::Adapters::Abstract

Class Method Details

.sideloading_classesObject



10
11
12
13
14
15
16
17
# File 'lib/graphiti/adapters/active_record.rb', line 10

def self.sideloading_classes
  {
    has_many: Graphiti::Adapters::ActiveRecord::HasManySideload,
    has_one: Graphiti::Adapters::ActiveRecord::HasOneSideload,
    belongs_to: Graphiti::Adapters::ActiveRecord::BelongsToSideload,
    many_to_many: Graphiti::Adapters::ActiveRecord::ManyToManySideload,
  }
end

Instance Method Details

#associate(parent, child, association_name, association_type) ⇒ Object



228
229
230
231
232
233
234
235
236
# File 'lib/graphiti/adapters/active_record.rb', line 228

def associate(parent, child, association_name, association_type)
  if activerecord_associate?(parent, child, association_name)
    association = parent.association(association_name)
    association.loaded!
    association.instance_variable_set(:@target, child)
  else
    super
  end
end

#associate_all(parent, children, association_name, association_type) ⇒ Object



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/graphiti/adapters/active_record.rb', line 207

def associate_all(parent, children, association_name, association_type)
  if activerecord_associate?(parent, children[0], association_name)
    association = parent.association(association_name)
    association.loaded!

    children.each do |child|
      if association_type == :many_to_many &&
          [:create, :update].include?(Graphiti.context[:namespace]) &&
          !parent.send(association_name).exists?(child.id)
        parent.send(association_name) << child
      else
        target = association.instance_variable_get(:@target)
        target |= [child]
        association.instance_variable_set(:@target, target)
      end
    end
  else
    super
  end
end

#average(scope, attr) ⇒ Float

Returns the average of the scope.

Examples:

ActiveRecord default

def average(scope, attr)
  scope.average(attr).to_f
end

Parameters:

  • scope

    the scope object we are chaining

  • attr (Symbol)

    corresponding stat attribute name

Returns:

  • (Float)

    the average of the scope



173
174
175
# File 'lib/graphiti/adapters/active_record.rb', line 173

def average(scope, attr)
  scope.average(attr).to_f
end

#base_scope(model) ⇒ Object



149
150
151
# File 'lib/graphiti/adapters/active_record.rb', line 149

def base_scope(model)
  model.all
end

#count(scope, attr) ⇒ Numeric

Returns the count of the scope.

Examples:

ActiveRecord default

def count(scope, attr)
  column = attr == :total ? :all : attr
  scope.uniq.count(column)
end

Parameters:

  • scope

    the scope object we are chaining

  • attr (Symbol)

    corresponding stat attribute name

Returns:

  • (Numeric)

    the count of the scope



164
165
166
167
168
169
170
# File 'lib/graphiti/adapters/active_record.rb', line 164

def count(scope, attr)
  if attr.to_sym == :total
    scope.distinct.count
  else
    scope.distinct.count(attr)
  end
end

#create(model_class, create_params) ⇒ Object



249
250
251
252
253
# File 'lib/graphiti/adapters/active_record.rb', line 249

def create(model_class, create_params)
  instance = model_class.new(create_params)
  instance.save
  instance
end

#destroy(model_instance) ⇒ Object



267
268
269
270
# File 'lib/graphiti/adapters/active_record.rb', line 267

def destroy(model_instance)
  model_instance.destroy
  model_instance
end

#disassociate(parent, child, association_name, association_type) ⇒ Object

When a has_and_belongs_to_many relationship, we don’t have a foreign key that can be null’d. Instead, go through the ActiveRecord API.



241
242
243
244
245
246
# File 'lib/graphiti/adapters/active_record.rb', line 241

def disassociate(parent, child, association_name, association_type)
  if association_type == :many_to_many
    parent.send(association_name).delete(child)
  end
  # Nothing to do in the else case, happened when we merged foreign key
end

#filter_datetime_eq(scope, attribute, value, is_not: false) ⇒ Object

Ensure fractional seconds don’t matter



133
134
135
136
137
# File 'lib/graphiti/adapters/active_record.rb', line 133

def filter_datetime_eq(scope, attribute, value, is_not: false)
  ranges = value.map { |v| (v..v + 1.second - 0.00000001) }
  clause = {attribute => ranges}
  is_not ? scope.where.not(clause) : scope.where(clause)
end

#filter_datetime_lte(scope, attribute, value) ⇒ Object



143
144
145
146
147
# File 'lib/graphiti/adapters/active_record.rb', line 143

def filter_datetime_lte(scope, attribute, value)
  value = value.map { |v| v + 1.second - 0.00000001 }
  column = scope.klass.arel_table[attribute]
  scope.where(column.lteq_any(value))
end

#filter_datetime_not_eq(scope, attribute, value) ⇒ Object



139
140
141
# File 'lib/graphiti/adapters/active_record.rb', line 139

def filter_datetime_not_eq(scope, attribute, value)
  filter_datetime_eq(scope, attribute, value, is_not: true)
end

#filter_eq(scope, attribute, value) ⇒ Object Also known as: filter_integer_eq, filter_float_eq, filter_big_decimal_eq, filter_date_eq, filter_boolean_eq, filter_uuid_eq, filter_enum_eq



19
20
21
# File 'lib/graphiti/adapters/active_record.rb', line 19

def filter_eq(scope, attribute, value)
  scope.where(attribute => value)
end

#filter_gt(scope, attribute, value) ⇒ Object Also known as: filter_integer_gt, filter_float_gt, filter_big_decimal_gt, filter_datetime_gt, filter_date_gt



93
94
95
96
# File 'lib/graphiti/adapters/active_record.rb', line 93

def filter_gt(scope, attribute, value)
  column = column_for(scope, attribute)
  scope.where(column.gt_any(value))
end

#filter_gte(scope, attribute, value) ⇒ Object Also known as: filter_integer_gte, filter_float_gte, filter_big_decimal_gte, filter_datetime_gte, filter_date_gte



103
104
105
106
# File 'lib/graphiti/adapters/active_record.rb', line 103

def filter_gte(scope, attribute, value)
  column = column_for(scope, attribute)
  scope.where(column.gteq_any(value))
end

#filter_lt(scope, attribute, value) ⇒ Object Also known as: filter_integer_lt, filter_float_lt, filter_big_decimal_lt, filter_datetime_lt, filter_date_lt



113
114
115
116
# File 'lib/graphiti/adapters/active_record.rb', line 113

def filter_lt(scope, attribute, value)
  column = column_for(scope, attribute)
  scope.where(column.lt_any(value))
end

#filter_lte(scope, attribute, value) ⇒ Object Also known as: filter_integer_lte, filter_float_lte, filter_big_decimal_lte, filter_date_lte



123
124
125
126
# File 'lib/graphiti/adapters/active_record.rb', line 123

def filter_lte(scope, attribute, value)
  column = column_for(scope, attribute)
  scope.where(column.lteq_any(value))
end

#filter_not_eq(scope, attribute, value) ⇒ Object Also known as: filter_integer_not_eq, filter_float_not_eq, filter_big_decimal_not_eq, filter_date_not_eq, filter_boolean_not_eq, filter_uuid_not_eq, filter_enum_not_eq



30
31
32
# File 'lib/graphiti/adapters/active_record.rb', line 30

def filter_not_eq(scope, attribute, value)
  scope.where.not(attribute => value)
end

#filter_string_eq(scope, attribute, value, is_not: false) ⇒ Object



41
42
43
44
45
# File 'lib/graphiti/adapters/active_record.rb', line 41

def filter_string_eq(scope, attribute, value, is_not: false)
  column = column_for(scope, attribute)
  clause = column.lower.eq_any(value.map(&:downcase))
  is_not ? scope.where.not(clause) : scope.where(clause)
end

#filter_string_eql(scope, attribute, value, is_not: false) ⇒ Object



47
48
49
50
# File 'lib/graphiti/adapters/active_record.rb', line 47

def filter_string_eql(scope, attribute, value, is_not: false)
  clause = {attribute => value}
  is_not ? scope.where.not(clause) : scope.where(clause)
end

#filter_string_match(scope, attribute, value, is_not: false) ⇒ Object



82
83
84
85
86
87
# File 'lib/graphiti/adapters/active_record.rb', line 82

def filter_string_match(scope, attribute, value, is_not: false)
  column = column_for(scope, attribute)
  map = value.map { |v| "%#{v.downcase}%" }
  clause = column.lower.matches_any(map)
  is_not ? scope.where.not(clause) : scope.where(clause)
end

#filter_string_not_eq(scope, attribute, value) ⇒ Object



52
53
54
# File 'lib/graphiti/adapters/active_record.rb', line 52

def filter_string_not_eq(scope, attribute, value)
  filter_string_eq(scope, attribute, value, is_not: true)
end

#filter_string_not_eql(scope, attribute, value) ⇒ Object



56
57
58
# File 'lib/graphiti/adapters/active_record.rb', line 56

def filter_string_not_eql(scope, attribute, value)
  filter_string_eql(scope, attribute, value, is_not: true)
end

#filter_string_not_match(scope, attribute, value) ⇒ Object



89
90
91
# File 'lib/graphiti/adapters/active_record.rb', line 89

def filter_string_not_match(scope, attribute, value)
  filter_string_match(scope, attribute, value, is_not: true)
end

#filter_string_not_prefix(scope, attribute, value) ⇒ Object



67
68
69
# File 'lib/graphiti/adapters/active_record.rb', line 67

def filter_string_not_prefix(scope, attribute, value)
  filter_string_prefix(scope, attribute, value, is_not: true)
end

#filter_string_not_suffix(scope, attribute, value) ⇒ Object



78
79
80
# File 'lib/graphiti/adapters/active_record.rb', line 78

def filter_string_not_suffix(scope, attribute, value)
  filter_string_suffix(scope, attribute, value, is_not: true)
end

#filter_string_prefix(scope, attribute, value, is_not: false) ⇒ Object



60
61
62
63
64
65
# File 'lib/graphiti/adapters/active_record.rb', line 60

def filter_string_prefix(scope, attribute, value, is_not: false)
  column = column_for(scope, attribute)
  map = value.map { |v| "#{v}%" }
  clause = column.lower.matches_any(map)
  is_not ? scope.where.not(clause) : scope.where(clause)
end

#filter_string_suffix(scope, attribute, value, is_not: false) ⇒ Object



71
72
73
74
75
76
# File 'lib/graphiti/adapters/active_record.rb', line 71

def filter_string_suffix(scope, attribute, value, is_not: false)
  column = column_for(scope, attribute)
  map = value.map { |v| "%#{v}" }
  clause = column.lower.matches_any(map)
  is_not ? scope.where.not(clause) : scope.where(clause)
end

#maximum(scope, attr) ⇒ Numeric

Returns the maximum value of the scope.

Examples:

ActiveRecord default

def maximum(scope, attr)
  scope.maximum(attr)
end

Parameters:

  • scope

    the scope object we are chaining

  • attr (Symbol)

    corresponding stat attribute name

Returns:

  • (Numeric)

    the maximum value of the scope



183
184
185
# File 'lib/graphiti/adapters/active_record.rb', line 183

def maximum(scope, attr)
  scope.maximum(attr)
end

#minimum(scope, attr) ⇒ Numeric

Returns the maximum value of the scope.

Examples:

ActiveRecord default

def maximum(scope, attr)
  scope.maximum(attr)
end

Parameters:

  • scope

    the scope object we are chaining

  • attr (Symbol)

    corresponding stat attribute name

Returns:

  • (Numeric)

    the maximum value of the scope



188
189
190
# File 'lib/graphiti/adapters/active_record.rb', line 188

def minimum(scope, attr)
  scope.minimum(attr)
end

#order(scope, attribute, direction) ⇒ Object

Returns the scope.

Examples:

ActiveRecord default

def order(scope, attribute, direction)
  scope.order(attribute => direction)
end

Parameters:

  • scope

    The scope object we are chaining

  • attribute (Symbol)

    The attribute name we are sorting

  • direction (Symbol)

    The direction we are sorting (asc/desc)

Returns:

  • the scope



154
155
156
# File 'lib/graphiti/adapters/active_record.rb', line 154

def order(scope, attribute, direction)
  scope.order(attribute => direction)
end

#paginate(scope, current_page, per_page) ⇒ Object

Returns the scope.

Examples:

ActiveRecord default

# via kaminari gem
def paginate(scope, current_page, per_page)
  scope.page(current_page).per(per_page)
end

Parameters:

  • scope

    The scope object we are chaining

  • current_page (Integer)

    The current page number

  • per_page (Integer)

    The number of results per page

Returns:

  • the scope



159
160
161
# File 'lib/graphiti/adapters/active_record.rb', line 159

def paginate(scope, current_page, per_page)
  scope.page(current_page).per(per_page)
end

#resolve(scope) ⇒ Object

Resolve the scope. This is where you’d actually fire SQL, actually make an HTTP call, etc.

Examples:

ActiveRecordDefault

def resolve(scope)
  scope.to_a
end

Suggested Customization

# When making a service call, we suggest this abstraction
# 'scope' here is a hash
def resolve(scope)
  # The implementation of .where can be whatever you want
  SomeModelClass.where(scope)
end

Parameters:

  • scope

    The scope object to resolve

Returns:

  • an array of Model instances

See Also:



193
194
195
# File 'lib/graphiti/adapters/active_record.rb', line 193

def resolve(scope)
  scope.to_a
end

#save(model_instance) ⇒ Object



262
263
264
265
# File 'lib/graphiti/adapters/active_record.rb', line 262

def save(model_instance)
  model_instance.save
  model_instance
end

#sum(scope, attr) ⇒ Numeric

Returns the sum of the scope.

Examples:

ActiveRecord default

def sum(scope, attr)
  scope.sum(attr)
end

Parameters:

  • scope

    the scope object we are chaining

  • attr (Symbol)

    corresponding stat attribute name

Returns:

  • (Numeric)

    the sum of the scope



178
179
180
# File 'lib/graphiti/adapters/active_record.rb', line 178

def sum(scope, attr)
  scope.sum(attr)
end

#transaction(model_class) ⇒ Object

Run this write request within an ActiveRecord transaction

Parameters:

  • model_class (Class)

    The ActiveRecord class we are saving

Returns:

  • Result of yield

See Also:



201
202
203
204
205
# File 'lib/graphiti/adapters/active_record.rb', line 201

def transaction(model_class)
  model_class.transaction do
    yield
  end
end

#update(model_class, update_params) ⇒ Object



256
257
258
259
260
# File 'lib/graphiti/adapters/active_record.rb', line 256

def update(model_class, update_params)
  instance = model_class.find(update_params.delete(:id))
  instance.update_attributes(update_params)
  instance
end