Created
October 11, 2022 10:14
-
-
Save bguban/c18aa0e625d1962fd79ed7980e808268 to your computer and use it in GitHub Desktop.
Extra graphiti functionality
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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