How to refactor #filtered method?
In Hanami there is no way to make a chain of queries (filters) in ActiveRecord-style. I would like to get a methods like ActiveRecord filters.
Now: documents.filtered(genre: 'news', min_published_at: from, max_published_at: to, skip: 30)
What I want: documents.with_genre('news').published_between(from, to).skip(30)
class DocumentRepository < Hanami::Repository
GENRES = DbSchema.current_schema.enum(:document_genre).values.map(&:to_s)
DOCUMENTS_PER_PAGE = 30
associations do
has_many :boxes
has_many :urls
end
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/AbcSize
def filtered(params = {})
result = ordered.limit(DOCUMENTS_PER_PAGE)
result = result.where(genre: params[:genre]) if params.key?(:genre)
if params.key?(:min_created_at) && params.key?(:max_created_at)
date_range = params[:min_created_at]..params[:max_created_at]
result = result.where(created_at: date_range)
end
if params.key?(:min_published_at) && params.key?(:max_published_at)
date_range = params[:min_published_at]..params[:max_published_at]
result = result.where(published_at: date_range)
end
result = result.offset(params[:skip]) if params.key?(:skip)
result
end
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/AbcSize
def ordered
documents.order { created_at.desc }
end
end
Something along these lines might work, but not sure how chaining these will poorly effect performance or results, but you can try it and it may lead you to the answer you want
UPDATED
If you really want chaining this is close to what you want.
Call it like this assuming this is an instance variable of
DocumentRepositoryBy returning
selfin each instance method you're able to chain the calls on the instance.Original answer
This way works but uses similar syntax in your current call.
You can call it like: