Skip to content

Instantly share code, notes, and snippets.

@wojtha
Created November 9, 2017 18:10
Show Gist options
  • Save wojtha/05f26f0a45ae260ab555396d89e16136 to your computer and use it in GitHub Desktop.
Save wojtha/05f26f0a45ae260ab555396d89e16136 to your computer and use it in GitHub Desktop.
ActiveRecord::Finder implementation with chainable scopes!
module ActiveRecord
module Finder
module Scope
extend ActiveSupport::Concern
attr_reader :relation
def initialize(relation)
@relation = relation
end
def default_scope
relation.clone
end
def to_relation
relation.clone
end
module ClassMethods
def scope(name, body)
unless body.respond_to?(:call)
raise ArgumentError, "The scope body needs to be callable."
end
if respond_to?(name, true)
raise ArgumentError, "Creating scope :#{name}. Overwriting existing method #{self.name}.#{name}."
end
if body.respond_to?(:to_proc)
define_method(name) do |*args|
scope = default_scope.scoping { relation.model.instance_exec(*args, &body) }
self.class.new(scope || default_scope)
end
else
define_method(name) do |*args|
scope = default_scope.scoping { body.call(*args) }
self.class.new(scope || default_scope)
end
end
end
def private_scope(name, body)
scope(name, body)
private name
end
alias_method :pscope, :private_scope
end
end
module Model
extend ActiveSupport::Concern
include ActiveRecord::Finder::Scope
def initialize(relation = nil)
super(relation || self.class.model.all)
end
module ClassMethods
def finder_for(model)
@model = model
end
def model
@model
end
end
end
end
end
class TopicFinder
include ActiveRecord::Finder::Model
finder_for Topic
def list_active_for_owned_by(owner)
active.owned_by(owner).relation
end
def list_inactive_for_owned_by(owner)
inactive.owned_by(owner).relation
end
private_scope :active, -> { where(archived: false) }
private_scope :inactive, -> { where(archived: true) }
private_scope :owned_by, ->(owner) { where(owner_id: owner.id, owner_type: owner.class.to_s) }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment