Skip to content

Instantly share code, notes, and snippets.

@bguban
Created October 11, 2022 10:14
Show Gist options
  • Save bguban/c18aa0e625d1962fd79ed7980e808268 to your computer and use it in GitHub Desktop.
Save bguban/c18aa0e625d1962fd79ed7980e808268 to your computer and use it in GitHub Desktop.
Extra graphiti functionality
# ApplicationResource is similar to ApplicationRecord - a base class that
# holds configuration/methods for subclasses.
# All Resources should inherit from ApplicationResource.
class ApplicationResource < Graphiti::Resource
# Use the ActiveRecord Adapter for all subclasses.
# Subclasses can still override this default.
self.abstract_class = true
self.adapter = Graphiti::Adapters::ActiveRecord
self.base_url = Rails.application.routes.default_url_options[:host]
self.endpoint_namespace = '/api/v1'
#### Extra graphiti functionality #####
# `assignable` check handles right before assigning a new value to the attribute. It has access to the
# `model_instance`, `attr_name` and all the `attributes`.
# It works after `writable` check and after access to the database (for update actions). That's why for performance
# reasons if you don't need access to the model_instance and attributes it's better to use `writable`.
#
# ```
# self.attributes_assignable_by_default = :owner?
#
# or
#
# attribute :attr_name, assignable: :owner?
#
# def owner?(model_instance, _attr_name, _attributes)
# model_instance.user_id == context.current_user&.id
# end
# ```
class_attribute :attributes_assignable_by_default, instance_accessor: false, default: true
def save(model_instance, meta = nil)
super if model_instance.errors.blank?
model_instance
end
def assign_attributes(model_instance, update_params, meta = nil)
update_params.each_key do |attr|
assignable = attributes.dig(attr, :assignable) || self.class.attributes_assignable_by_default
assignable = send(assignable, model_instance, attr, update_params) if assignable.is_a?(Symbol)
model_instance.errors.add(attr, :unassignable_attribute, message: "cannot be assigned") unless assignable
end
super if model_instance.errors.blank?
end
# if several users can have a read access to the resource but only some of them have write access then you can't use
# `base_scope` to prevent deletion. `resource_deletable` check says if the resource can be deleted.
#
# ```
# self.resource_deletable = :owner?
#
# def owner?(model_instance)
# model_instance.user_id == context.current_user&.id
# end
# ```
class_attribute :resource_deletable, instance_accessor: false, default: true
def delete(model_instance)
deletable = self.class.resource_deletable
deletable = send(deletable, model_instance) if deletable.is_a?(Symbol)
if deletable
super
else
model_instance.errors.add(:base, "can't be deleted")
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment