Class: Graphiti::Resource

Inherits:
Object show all
Includes:
Links, Configuration, DSL, Documentation, Interface, Persistence, Sideloading
Defined in:
lib/graphiti/resource.rb,
lib/graphiti/resource/dsl.rb,
lib/graphiti/resource/remote.rb,
lib/graphiti/resource/interface.rb,
lib/graphiti/resource/persistence.rb,
lib/graphiti/resource/sideloading.rb,
lib/graphiti/resource/polymorphism.rb,
lib/graphiti/resource/configuration.rb,
lib/graphiti/resource/documentation.rb

Direct Known Subclasses

Query::RemoteSideloadResource

Defined Under Namespace

Modules: Configuration, DSL, Documentation, Interface, Persistence, Polymorphism, Remote, Sideloading

Constant Summary

Constants included from Links

Links::DEFAULT_ACTIONS

Constants included from Configuration

Configuration::DEFAULT_MAX_PAGE_SIZE

Instance Attribute Summary

Attributes included from Persistence

#assigned_model

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Persistence

#assign, #assign_attributes, #build, #create, #delete, #destroy, #save, #update, #with_assigned_model

Methods included from Sideloading

included

Methods included from Configuration

#adapter, #all_attributes, #attributes, #default_filters, #extra_attributes, #filters, #get_attr, #get_attr!, #grouped_filters, #pagination, #sort_all, #sorts, #stats

Class Method Details

.contextObject



46
47
48
# File 'lib/graphiti/resource.rb', line 46

def self.context
  Graphiti.context[:object]
end

.context_namespaceObject



65
66
67
68
# File 'lib/graphiti/resource.rb', line 65

def self.context_namespace
  Graphiti::DEPRECATOR.deprecation_warning(:context_namespace, "Use #current_action instead")
  current_action
end

.current_actionObject

Rails sets this from action_name, so it is whatever the controller action is called, not a fixed list. Persistence overrides it with :create/:update while saving, and :show while resolving sideloads afterwards.



57
58
59
# File 'lib/graphiti/resource.rb', line 57

def self.current_action
  Graphiti.context[:namespace]
end

Instance Method Details

#after_commit(model, metadata) ⇒ Object



181
182
183
184
185
186
# File 'lib/graphiti/resource.rb', line 181

def after_commit(model, )
  hooks = self.class.config[:after_commit][[:method]] || []
  hooks.each do |hook|
    instance_exec(model, , &hook)
  end
end

#after_filtering(scope) ⇒ Object



23
24
25
# File 'lib/graphiti/resource.rb', line 23

def after_filtering(scope)
  scope
end

#after_graph_persist(model, metadata) ⇒ Object



167
168
169
170
171
172
# File 'lib/graphiti/resource.rb', line 167

def after_graph_persist(model, )
  hooks = self.class.config[:after_graph_persist][[:method]] || []
  hooks.each do |hook|
    instance_exec(model, , &hook)
  end
end

#around_scoping(scope, query_hash) {|scope| ... } ⇒ Object

Yields:

  • (scope)


11
12
13
14
15
16
17
18
19
20
21
# File 'lib/graphiti/resource.rb', line 11

def around_scoping(scope, query_hash)
  extra_fields = query_hash[:extra_fields] || {}
  extra_fields = extra_fields[type] || []
  extra_fields.each do |name|
    if (config = self.class.config[:extra_attributes][name])
      scope = instance_exec(scope, &config[:hook]) if config[:hook]
    end
  end

  yield scope
end

#assign_with_relationships(meta, attributes, relationships, caller_model = nil, foreign_key = nil, model_instance: nil) ⇒ Object

TODO: make foreign_key a keyword once the satellite gems are rolled in - they call these positionally



139
140
141
142
143
144
# File 'lib/graphiti/resource.rb', line 139

def assign_with_relationships(meta, attributes, relationships, caller_model = nil, foreign_key = nil, model_instance: nil)
  persistence = Graphiti::Util::Persistence \
    .new(self, meta, attributes, relationships, caller_model, foreign_key,
      assigned_model: model_instance)
  persistence.assign
end

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



130
131
132
# File 'lib/graphiti/resource.rb', line 130

def associate(parent, child, association_name, type)
  adapter.associate(parent, child, association_name, type)
end

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



126
127
128
# File 'lib/graphiti/resource.rb', line 126

def associate_all(parent, children, association_name, type)
  adapter.associate_all(parent, children, association_name, type)
end

#base_scopeObject



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

def base_scope
  adapter.base_scope(model)
end

#before_commit(model, metadata) ⇒ Object



174
175
176
177
178
179
# File 'lib/graphiti/resource.rb', line 174

def before_commit(model, )
  hooks = self.class.config[:before_commit][[:method]] || []
  hooks.each do |hook|
    instance_exec(model, , &hook)
  end
end

#before_resolve(scope, query) ⇒ Object



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

def before_resolve(scope, query)
  scope
end

#build_scope(base, query, opts = {}) ⇒ Object



74
75
76
# File 'lib/graphiti/resource.rb', line 74

def build_scope(base, query, opts = {})
  Scope.new(base, self, query, opts)
end

#contextObject



50
51
52
# File 'lib/graphiti/resource.rb', line 50

def context
  self.class.context
end

#context_namespaceObject



70
71
72
# File 'lib/graphiti/resource.rb', line 70

def context_namespace
  self.class.context_namespace
end

#current_actionObject



61
62
63
# File 'lib/graphiti/resource.rb', line 61

def current_action
  self.class.current_action
end

#decorate_record(record, index = nil) ⇒ Object



31
32
33
34
35
36
37
38
# File 'lib/graphiti/resource.rb', line 31

def decorate_record(record, index = nil)
  unless record.instance_variable_get(:@__graphiti_serializer)
    serializer = serializer_for(record)
    record.instance_variable_set(:@__graphiti_serializer, serializer)
    record.instance_variable_set(:@__graphiti_resource, self)
    record.instance_variable_set(:@__graphiti_index, index) if index
  end
end

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



134
135
136
# File 'lib/graphiti/resource.rb', line 134

def disassociate(parent, child, association_name, type)
  adapter.disassociate(parent, child, association_name, type)
end

#guard_modelObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The model a writable guard is being asked about. Resolved lazily and memoized, so it costs nothing unless a guard asks for it, and is only resolved once per payload. On create, this is a new unsaved instance.



96
97
98
99
100
101
102
103
104
105
106
# File 'lib/graphiti/resource.rb', line 96

def guard_model
  return @guard_model if defined?(@guard_model)

  @guard_model = if !defined?(@guarded_write)
    nil
  elsif @guarded_write[:action] == :create || @guarded_write[:id].nil?
    build(model)
  else
    self.class._find(id: @guarded_write[:id]).data
  end
end


204
205
206
207
208
# File 'lib/graphiti/resource.rb', line 204

def links(model)
  self.class.links.each_with_object({}) do |(name, blk), memo|
    memo[name] = instance_exec(model, &blk)
  end
end

#links?Boolean

Returns:

  • (Boolean)


200
201
202
# File 'lib/graphiti/resource.rb', line 200

def links?
  self.class.links.any?
end

#persist_with_relationships(meta, attributes, relationships, caller_model = nil, foreign_key = nil, assigned_model: nil) ⇒ Object



146
147
148
149
150
151
# File 'lib/graphiti/resource.rb', line 146

def persist_with_relationships(meta, attributes, relationships, caller_model = nil, foreign_key = nil, assigned_model: nil)
  persistence = Graphiti::Util::Persistence \
    .new(self, meta, attributes, relationships, caller_model, foreign_key,
      assigned_model: assigned_model)
  persistence.run
end

#resolve(scope) ⇒ Object



163
164
165
# File 'lib/graphiti/resource.rb', line 163

def resolve(scope)
  adapter.resolve(scope)
end

#serializer_for(model) ⇒ Object



27
28
29
# File 'lib/graphiti/resource.rb', line 27

def serializer_for(model)
  serializer
end

#stat(attribute, calculation) ⇒ Object



153
154
155
156
157
# File 'lib/graphiti/resource.rb', line 153

def stat(attribute, calculation)
  stats_dsl = stats[attribute] || stats[attribute.to_sym]
  raise Errors::StatNotFound.new(attribute, calculation) unless stats_dsl
  stats_dsl.calculation(calculation)
end

#transactionObject



188
189
190
191
192
193
194
195
196
197
198
# File 'lib/graphiti/resource.rb', line 188

def transaction
  response = nil
  begin
    adapter.transaction(model) do
      response = yield
    end
  rescue Errors::ValidationError => e
    response = {result: e.validation_response}
  end
  response
end

#typecast(name, value, flag) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/graphiti/resource.rb', line 108

def typecast(name, value, flag)
  att = get_attr!(name, flag, request: true)
  type_name = att[:type]
  if flag == :filterable
    type_name = filters[name][:type]
  end
  type = Graphiti::Types[type_name]
  return if value.nil? && type[:kind] != "array"
  begin
    flag = :read if flag == :readable
    flag = :write if flag == :writable
    flag = :params if [:sortable, :filterable].include?(flag)
    type[flag][value]
  rescue => e
    raise Errors::TypecastFailed.new(self, name, value, e, type_name)
  end
end

#with_context(object, namespace = nil) ⇒ Object



40
41
42
43
44
# File 'lib/graphiti/resource.rb', line 40

def with_context(object, namespace = nil)
  Graphiti.with_context(object, namespace) do
    yield
  end
end

#with_guarded_write(action, id) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Exposes write context to attribute guards for the duration of the block.



84
85
86
87
88
89
90
# File 'lib/graphiti/resource.rb', line 84

def with_guarded_write(action, id)
  @guarded_write = {action: action, id: id}
  yield
ensure
  remove_instance_variable(:@guarded_write) if defined?(@guarded_write)
  remove_instance_variable(:@guard_model) if defined?(@guard_model)
end