Skip to content

Instantly share code, notes, and snippets.

@dmitry
Last active October 28, 2020 11:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmitry/3e423a473ef30fec91fdc6c6bbe0bd45 to your computer and use it in GitHub Desktop.
Save dmitry/3e423a473ef30fec91fdc6c6bbe0bd45 to your computer and use it in GitHub Desktop.
class ApplicationPolicy < ActionPolicy::Base
scope_matcher :action_controller_params, Types::Base::InputObject
class ParamsFilter < ActionController::Parameters
include ActionPolicy::Behaviour
include ActionPolicy::Behaviours::ThreadMemoized
include ActionPolicy::Behaviours::Memoized
include ActionPolicy::Behaviours::Namespaced
attr_accessor :user, :record, :attributes, :parent, :root
def initialize(params = {})
super(params.kind_of?(ActionController::Parameters) ? params.send(:parameters) : params.to_h)
self.user = user
self.attributes = []
end
def attribute(*attributes)
self.attributes += Array.wrap(attributes)
end
# associations are without `_attributes` postfix
def association(association_name)
association_attribute_name = association_name
if (association_params = parameters[association_attribute_name])
association = nil
association_record = if record.class.reflections.key?(association_name.to_s)
association = record.association(association_name)
record.send(association_name)
else
record.send(association_name)
end
unless association_record
association_record = new_record_for(association_name, association)
end
if association_record
attribute(
association_attribute_name => authorized(
self.class.new(association_params),
with: ActionPolicy.lookup(association_record),
context: {
user: user
},
scope_options: {
record: association_record,
attributes: true,
parent: record,
root: root
}
)
)
end
end
end
def permit_params
permit(attributes)
end
private
def policy(record = nil)
policy_for(
record: record || self.record,
context: {
user: user
}
)
end
def new_record_for(association_name, association)
reflection = association&.reflection
if !reflection || reflection.polymorphic?
record.class.send(
:"#{association_name}_class",
self[:"#{association_name}_type"]
)
else
reflection.klass.new
end
end
end
def self.params_filter(*args, &block)
filter = lambda do |params, record:, parent: nil, root: nil, attributes: false|
params_filter = ParamsFilter.new(params)
params_filter.user = user
params_filter.record = record
params_filter.parent = parent
params_filter.root = root
params_filter.instance_exec(&block)
if attributes
params_filter.attributes
else
params_filter.permit_params
end
end
scope_for(:action_controller_params, *args, &filter)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment