Skip to content

Commit

Permalink
feat: allow finders to be inherited
Browse files Browse the repository at this point in the history
feat: change configuration from hash to configuration object
  • Loading branch information
seuros committed Jan 11, 2024
1 parent 108145b commit 8e13b29
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 74 deletions.
2 changes: 1 addition & 1 deletion lib/trailblazer/finder/activities/prepare_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class Finder
module Activities
class PrepareAdapter < Trailblazer::Activity::Railway
def set_adapter(ctx, **)
ctx[:adapter] = ctx.dig(:config, :adapter) || "Basic"
ctx[:adapter] = ctx[:config].adapter
end

def validate_adapter(_ctx, adapter:, **)
Expand Down
8 changes: 4 additions & 4 deletions lib/trailblazer/finder/activities/prepare_entity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ module Trailblazer
class Finder
module Activities
class PrepareEntity < Trailblazer::Activity::Railway
def validate_entity(ctx, **)
ctx.dig(:options, :entity) || ctx.dig(:config, :entity)
def validate_entity(ctx, config:, **)
ctx.dig(:options, :entity) || config.entity
end

def invalid_entity_error(ctx, **)
(ctx[:errors] ||= []) << {entity: "Invalid entity specified"}
end

def set_entity(ctx, **)
ctx[:entity] = ctx.dig(:options, :entity) || instance_eval(&ctx[:config][:entity])
def set_entity(ctx, config:, **)
ctx[:entity] = ctx.dig(:options, :entity) || instance_eval(&config.entity)
end

step :validate_entity
Expand Down
8 changes: 4 additions & 4 deletions lib/trailblazer/finder/activities/prepare_filters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ module Trailblazer
class Finder
module Activities
class PrepareFilters < Trailblazer::Activity::Railway
def validate_filters(ctx, **)
filters = ctx.dig(:config, :filters)
def validate_filters(_ctx, config:, **)
filters = config.filters
filters.each do |key, _value|
return false if !filters[key][:with].nil? && !filters[key][:with].is_a?(Symbol)
end
Expand All @@ -16,8 +16,8 @@ def invalid_filters_error(ctx, **)
(ctx[:errors] ||= []) << {filters: "One or more filters are missing a with method definition"}
end

def set_filters(ctx, **)
ctx[:filters] = ctx[:config][:filters]
def set_filters(ctx, config:, **)
ctx[:filters] = config.filters
end

step :validate_filters
Expand Down
10 changes: 5 additions & 5 deletions lib/trailblazer/finder/activities/prepare_paging.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ module Trailblazer
class Finder
module Activities
class PreparePaging < Trailblazer::Activity::Railway
def check_paging(ctx, **)
paging = ctx[:config][:paging] || nil
return false if ctx[:config][:paging].empty? || paging.nil?
def check_paging(_ctx, config:, **)
paging = config.paging
return false if config.paging.empty? || paging.nil?

true
end

def set_paging(ctx, **)
ctx[:paging] = ctx.dig(:config, :paging) || {}
def set_paging(ctx, config:, **)
ctx[:paging] = config.paging
ctx[:paging][:current_page] = ctx.dig(:params, :page) || 1
return true unless ctx[:params][:per_page]

Expand Down
12 changes: 6 additions & 6 deletions lib/trailblazer/finder/activities/prepare_properties.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ module Trailblazer
class Finder
module Activities
class PrepareProperties < Trailblazer::Activity::Railway
def check_property_types(ctx, **)
properties = ctx[:config][:properties] || {}
def check_property_types(_ctx, config:, **)
properties = config.properties
return true if properties.empty?

properties.each do |key, _value|
return !properties[key][:type].nil?
end
end

def validate_property_types(ctx, **)
properties = ctx[:config][:properties] || {}
def validate_property_types(_ctx, config:, **)
properties = config.properties
return true if properties.empty?

properties.each do |key, _value|
Expand All @@ -26,8 +26,8 @@ def invalid_properties_error(ctx, **)
(ctx[:errors] ||= []) << {properties: "One or more properties are missing a valid type"}
end

def set_properties(ctx, **)
ctx[:properties] = ctx[:config][:properties]
def set_properties(ctx, config:, **)
ctx[:properties] = config.properties
end

step :check_property_types
Expand Down
12 changes: 6 additions & 6 deletions lib/trailblazer/finder/activities/prepare_sorting.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ module Trailblazer
class Finder
module Activities
class PrepareSorting < Trailblazer::Activity::Railway
def check_sorting(ctx, **)
sorting = ctx[:config][:sorting] || nil
return true unless ctx[:config][:sorting].empty? || sorting.nil?
def check_sorting(_ctx, config:, **)
sorting = config.sorting
return true unless sorting.empty? || sorting.nil?
end

def set_sorting(ctx, **)
def set_sorting(ctx, config:, **)
return true if ctx[:params][:sort].nil?

sorting = ctx[:params][:sort]
config = ctx[:config][:sorting]
sorting_config = config.sorting
ctx[:sorting] = ctx[:sorting] || {}
sorting.split(",").each do |sorter|
spt = sorter.split
ctx[:sorting][spt[0]] = fetch_sort_direction(config[spt[0].to_sym], spt[1]) if config.include?(spt[0].to_sym)
ctx[:sorting][spt[0]] = fetch_sort_direction(sorting_config[spt[0].to_sym], spt[1]) if sorting_config.include?(spt[0].to_sym)
end
end

Expand Down
7 changes: 2 additions & 5 deletions lib/trailblazer/finder/activities/process_adapters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def set_adapter((ctx, _flow_options), **)
end

def set_paginator(ctx, **)
paginator = ctx.dig(:config, :paginator)
paginator = ctx[:config].paginator
return true unless paginator
return false unless EXT_ORM_ADAPTERS.(ctx[:orm][:adapter])
return false unless PAGING_ADAPTERS.(paginator)
Expand All @@ -26,10 +26,7 @@ def set_paginator(ctx, **)

def invalid_paginator_error(ctx, **)
(ctx[:errors] ||= []) << {
paginator: "Can't use paginator #{ctx.dig(
:config,
:paginator
)} without using an ORM like ActiveRecord or Sequel"
paginator: "Can't use paginator #{ctx[:config].paginator} without using an ORM like ActiveRecord or Sequel"
}
end

Expand Down
91 changes: 57 additions & 34 deletions lib/trailblazer/finder/dsl.rb
Original file line number Diff line number Diff line change
@@ -1,72 +1,95 @@
# frozen_string_literal: true

module Trailblazer
class Finder
class Configuration
attr_accessor :entity, :paging, :properties, :sorting,
:filters, :adapter, :paginator

def initialize
@paging = {}
@properties = {}
@sorting = {}
@filters = {}
@paginator = nil
@adapter = "Basic"
end

def clone
new_config = Configuration.new
new_config.entity = entity
new_config.paging = paging.clone
new_config.properties = properties.clone
new_config.sorting = sorting.clone
new_config.filters = filters.clone
new_config.adapter = adapter
new_config.paginator = paginator
new_config
end
end

module Dsl
def config
@config ||= apply_config({})
@config ||= Configuration.new
end


def inherited(base)
## We don't want to inherit the config from Trailblazer::Finder
return if name == 'Trailblazer::Finder'

base.apply_config(config)
base.config = config.clone
end

def entity(&block)
config[:entity] = block
config.entity = block
end

def paging(**options)
config[:paging][:per_page] = options[:per_page] || 25
config[:paging][:min_per_page] = options[:min_per_page] || 10
config[:paging][:max_per_page] = options[:max_per_page] || 100
def paging(per_page: 25, min_per_page: 10, max_per_page: 100)
config.paging[:per_page] = per_page
config.paging[:min_per_page] = min_per_page
config.paging[:max_per_page] = max_per_page
end

def property(name, options = {})
config[:properties][name] = options
config[:properties][name][:type] = options[:type] || Types::String
config[:sorting][name] = options[:sort_direction] || :desc if options[:sortable]
config.properties[name] = options
config.properties[name][:type] = options[:type] || Types::String
config.sorting[name] = options[:sort_direction] || :desc if options[:sortable]
end

def filter_by(name, options = {}, &block)
filter_name = name.to_sym
config[:filters][filter_name] = {}
config[:filters][filter_name][:name] = name
config[:filters][filter_name][:with] = options[:with] if options.include?(:with)
config[:filters][filter_name][:block] = block || nil
config.filters[filter_name] = {}
config.filters[filter_name][:name] = name
config.filters[filter_name][:with] = options[:with] if options.include?(:with)
config.filters[filter_name][:block] = block || nil
end

def adapter(adapter)
config[:adapter] = adapter.to_s
def adapter(adapter_name)
config.adapter = adapter_name.to_s
end

def paginator(paginator)
config[:paginator] = paginator.to_s
def paginator(paginator_name)
config.paginator = paginator_name.to_s
end

def current_adapter
config[:adapter]
config.adapter
end

def current_paginator
config[:paginator]
config.paginator
end

def filters_count
config.filters.count
end

def apply_config(options, **)
return @config = options unless options.empty?

@config = {
actions: {},
entity: nil,
properties: {},
filters: {},
paging: {},
sorting: {},
adapters: []
}
def properties_count
config.properties.count
end

protected

attr_writer :config
end
end
end
2 changes: 2 additions & 0 deletions test/support/operations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ def apply_escaped_name(entity, _attribute, value)
end

class FinderInherited < FinderWithEntity
property :raw_price, type: Types::Float, sortable: true
filter_by :price, with: :apply_price
paginator 'Kaminari'

def apply_price(entity, _attribute, value)
return if value.blank?
Expand Down
12 changes: 6 additions & 6 deletions test/trailblazer/finder/dsl_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def new_finder(default_entity = [], filter = {}, &block)
property :value, type: Base
end

assert_equal finder.class.config[:adapter], 'ActiveRecord'
assert_equal finder.class.config.adapter, 'ActiveRecord'
end
end

Expand All @@ -62,7 +62,7 @@ def new_finder(default_entity = [], filter = {}, &block)
property :value, type: Base
end

assert_equal finder.class.config[:properties], value: { type: Trailblazer::Finder::Base }
assert_equal finder.class.config.properties, value: { type: Trailblazer::Finder::Base }
end
end

Expand All @@ -74,9 +74,9 @@ def new_finder(default_entity = [], filter = {}, &block)
property :value, type: Types::String
end

assert_equal finder.class.config[:paging][:per_page], 2
assert_equal finder.class.config[:paging][:min_per_page], 1
assert_equal finder.class.config[:paging][:max_per_page], 5
assert_equal finder.class.config.paging[:per_page], 2
assert_equal finder.class.config.paging[:min_per_page], 1
assert_equal finder.class.config.paging[:max_per_page], 5
end

it "does not load paging stuff if paging isn't called in the finder class" do
Expand All @@ -85,7 +85,7 @@ def new_finder(default_entity = [], filter = {}, &block)
property :value, type: Types::String
end

assert_empty finder.class.config[:paging]
assert_empty finder.class.config.paging
end
end

Expand Down
10 changes: 7 additions & 3 deletions test/trailblazer/operation/finder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,17 @@ class Operation::FinderSpec < Minitest::TrailblazerSpec
end


it 'Can work with inherited finders' do
it 'can inherit finders' do
assert_equal Product::Finders::FinderWithEntity.current_adapter, 'ActiveRecord'
assert_nil Product::Finders::FinderWithEntity.current_paginator
## the parent class has 1 filter and 2 properties and not being overwritten by the child class
assert_equal Product::Finders::FinderWithEntity.properties_count, 2
assert_equal Product::Finders::FinderWithEntity.filters_count, 1

assert_equal Product::Finders::FinderInherited.current_adapter, 'ActiveRecord'
assert_nil Product::Finders::FinderInherited.current_paginator
binding.irb
assert_equal Product::Finders::FinderInherited.current_paginator, 'Kaminari'
assert_equal Product::Finders::FinderInherited.properties_count, 3
assert_equal Product::Finders::FinderInherited.filters_count, 2
end
end
end

0 comments on commit 8e13b29

Please sign in to comment.