Class: Graphiti::Sideload::BelongsTo

Inherits:
Graphiti::Sideload show all
Defined in:
lib/graphiti/sideload/belongs_to.rb

Constant Summary

Constants inherited from Graphiti::Sideload

HOOK_ACTIONS, TYPES

Instance Attribute Summary

Attributes inherited from Graphiti::Sideload

#group_name, #link, #name, #parent, #parent_resource_class, #polymorphic_as

Instance Method Summary collapse

Methods inherited from Graphiti::Sideload

after_save, #always_include_resource_ids?, assign, #assign, assign_each, #assign_each, #associate, #associate_all, #association_name, #base_scope, #build_resource_proxy, #clear_resources, #create_remote_resource, #description, #disassociate, #errors, #fire_hooks!, #foreign_key, #future_resolve, #guarded?, hooks, #initialize, link, #link?, #link_extra_fields, #link_filter, #load, params, #parent_resource, #performant_assign?, #polymorphic_child?, #polymorphic_has_many?, #polymorphic_has_one?, #polymorphic_parent?, pre_load, #primary_key, #readable?, #remote?, #resolve, #resource, #resource_class, #resource_class_loaded?, scope, #scope, #shared_remote?, #single?, #writable?

Constructor Details

This class inherits a constructor from Graphiti::Sideload

Instance Method Details

#base_filter(parents) ⇒ Object



51
52
53
54
# File 'lib/graphiti/sideload/belongs_to.rb', line 51

def base_filter(parents)
  parent_ids = ids_for_parents(parents)
  {primary_key => parent_ids.join(",")}
end

#default_include_resource_ids?Boolean

Returns:

  • (Boolean)


6
7
8
# File 'lib/graphiti/sideload/belongs_to.rb', line 6

def default_include_resource_ids?
  linkage_from_foreign_key?
end

The foreign key can stand in for the related id only when the two hold the same value. base_filter matches the key against primary_key, so pointing that at another column means the key holds that column instead.

Returns:

  • (Boolean)


40
41
42
# File 'lib/graphiti/sideload/belongs_to.rb', line 40

def foreign_key_is_related_id?
  primary_key == :id
end

#ids_for_parents(parents) ⇒ Object



56
57
58
59
60
61
# File 'lib/graphiti/sideload/belongs_to.rb', line 56

def ids_for_parents(parents)
  parent_ids = parents.map(&foreign_key)
  parent_ids.compact!
  parent_ids.uniq!
  parent_ids
end

#infer_foreign_keyObject



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/graphiti/sideload/belongs_to.rb', line 63

def infer_foreign_key
  return parent.foreign_key if polymorphic_child?

  if resource.remote?
    namespace = namespace_for(resource.class)
    resource_name = resource.class.name
      .gsub("#{namespace}::", "")
      .gsub("Resource", "")
    if resource_name.include?(".remote")
      resource_name = resource_name.split(".remote")[0].split(".")[1]
    end
    :"#{resource_name.singularize.underscore}_id"
  else
    model = resource.model
    namespace = namespace_for(model)
    model_name = model.name.gsub("#{namespace}::", "")
    :"#{model_name.underscore}_id"
  end
end

#linkage_from_foreign_key?Boolean

The parent already carries the foreign key, and for a plain belongs_to that key is the related id, so linkage costs nothing. Anything that can change which record the relationship resolves to, or what type it carries, has to load the association instead:

- a scope/params block or a base_scope can filter out the record the
foreign key points at, so the key would claim a relationship the API
would not actually return
- a polymorphic target takes its type from the record, not from the
relationship, so the key alone cannot say what type the id has
- a remote resource has no local foreign key to read
- a custom primary_key points the relationship at some other column, so
the key holds that column's value rather than the related id

Returns:

  • (Boolean)


23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/graphiti/sideload/belongs_to.rb', line 23

def linkage_from_foreign_key?
  # Ask before resolving #resource: an unreadable relationship renders
  # nothing, and its resource class may not even be inferrable.
  return false unless readable?
  return false unless foreign_key_is_related_id?
  return false if polymorphic_child?
  return false if self.class.scope_proc || self.class.params_proc
  return false if @base_scope
  return false if remote?
  return false if resource.class.polymorphic.present?

  true
end

#load_params(parents, query) ⇒ Object



44
45
46
47
48
49
# File 'lib/graphiti/sideload/belongs_to.rb', line 44

def load_params(parents, query)
  query.hash.tap do |hash|
    hash[:filter] ||= {}
    hash[:filter].merge!(base_filter(parents))
  end
end

#typeObject



2
3
4
# File 'lib/graphiti/sideload/belongs_to.rb', line 2

def type
  :belongs_to
end