From b25759670ed13a4c321ee336856206ab2cc344ba Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Thu, 2 Sep 2021 11:01:05 +0100 Subject: [PATCH] Implement ransackable whitelisting --- app/models/application_record.rb | 1 + app/models/concerns/searchable.rb | 53 +++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 app/models/concerns/searchable.rb diff --git a/app/models/application_record.rb b/app/models/application_record.rb index e4478b1559..4149333756 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -4,6 +4,7 @@ class ApplicationRecord < ActiveRecord::Base include DelegateBelongsTo include Spree::Core::Permalinks include Spree::Preferences::Preferable + include Searchable self.abstract_class = true end diff --git a/app/models/concerns/searchable.rb b/app/models/concerns/searchable.rb new file mode 100644 index 0000000000..9891372b59 --- /dev/null +++ b/app/models/concerns/searchable.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +# Whitelists model attributes, scopes, and associations that can be searched on with Ransack. +# Exposes methods for defining the whitelists, eg: +# +# class Widget < ApplicationRecord +# searchable_attributes :number, :state +# searchable_scopes :activated, :disabled +# +# ... +# end + +module Searchable + extend ActiveSupport::Concern + + DEFAULT_SEARCHABLE_ATTRIBUTES = [ + :id, :name, :description, :created_at, :updated_at, :completed_at, :deleted_at + ].freeze + + included do + class_attribute :whitelisted_search_attributes, instance_accessor: false, default: [] + class_attribute :whitelisted_search_associations, instance_accessor: false, default: [] + class_attribute :whitelisted_search_scopes, instance_accessor: false, default: [] + end + + class_methods do + def ransackable_associations(*_args) + self.whitelisted_search_associations.map(&:to_s) + end + + def ransackable_attributes(*_args) + (DEFAULT_SEARCHABLE_ATTRIBUTES | self.whitelisted_search_attributes).map(&:to_s) + end + + def ransackable_scopes(*_args) + self.whitelisted_search_scopes.map(&:to_s) + end + + private + + def searchable_attributes(*attrs) + self.whitelisted_search_attributes = attrs + end + + def searchable_associations(*attrs) + self.whitelisted_search_associations = attrs + end + + def searchable_scopes(*attrs) + self.whitelisted_search_scopes = attrs + end + end +end