Last active
March 25, 2020 08:04
-
-
Save henrik/3666601 to your computer and use it in GitHub Desktop.
Share some parameter string filter between controller and view.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Suitable when a controller and view share some parameter string. | |
# | |
# E.g. view: | |
# | |
# link_to_unless(filter.blank?, "All", filter: filter.blank) | |
# link_to_unless(filter.some?, "Some", filter: filter.some) | |
# link_to_unless(filter.others?, "Others", filter: filter.others) | |
# | |
# Or maybe: | |
# | |
# - filter.blank_and_values.each do |value| | |
# link_to_unless(filter.value == value, t(:"filters.#{value || :blank}"), filter: value) | |
# | |
# ApplicationController: | |
# | |
# extend StringFilter::ActionControllerExtension | |
# | |
# Controller: | |
# | |
# filter_with :some, :others | |
# filter_with :pear, :apple, name: :fruit_filter | |
# | |
# def index | |
# do_whatever if filter.some? | |
# do_another if fruit_filter.pear? | |
# end | |
class StringFilter | |
class UnsupportedValueError < StandardError; end | |
def initialize(values, current_value) | |
@current_value = current_value | |
@values = values | |
unless blank? || values.map(&:to_s).include?(current_value.to_s) | |
raise UnsupportedValueError | |
end | |
values.each do |value| | |
define_singleton_method(:"#{value}?") { # def foo? | |
value.to_s == current_value.to_s # :foo.to_s == current_value.to_s | |
} # end | |
define_singleton_method(value) { # def foo | |
value.to_sym # :foo | |
} # end | |
end | |
end | |
def blank | |
nil | |
end | |
def value | |
if blank? | |
blank | |
else | |
send(current_value) | |
end | |
end | |
def values | |
@values | |
end | |
def blank_and_values | |
[blank] + values | |
end | |
def blank? | |
current_value.nil? || current_value.empty? | |
end | |
private | |
def current_value | |
@current_value | |
end | |
end | |
# Do: | |
# | |
# class ApplicationController < ActionController::Base | |
# extend StringFilter::ActionControllerExtension | |
# end | |
# | |
# Now any controller can get a string filter with e.g.: | |
# | |
# class MyController < ApplicationController | |
# filter_with :foo, :bar | |
# | |
# # This gives you `fruit_filter.pear` etc. | |
# filter_with :pear, :apple, name: :fruit_filter | |
# end | |
module StringFilter::ActionControllerExtension | |
def filter_with(*filters, name: :filter) | |
define_method(name) do | |
StringFilter.new(filters, params[name]) | |
end | |
private name | |
helper_method name | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "spec_helper" | |
require "string_filter" | |
describe StringFilter, "validating current value" do | |
it "allows known values" do | |
-> { StringFilter.new([:foo], "foo") }.should_not raise_exception | |
end | |
it "allows nil" do | |
-> { StringFilter.new([:foo], nil) }.should_not raise_exception | |
end | |
it "allows the empty string" do | |
-> { StringFilter.new([:foo], "") }.should_not raise_exception | |
end | |
it "disallows unknown values" do | |
-> { | |
StringFilter.new([:foo], "bar") | |
}.should raise_error(StringFilter::UnsupportedValueError) | |
end | |
end | |
describe StringFilter, "dynamic query methods" do | |
specify "they are true when the current value matches" do | |
StringFilter.new([:foo, :bar], "foo").foo?.should be_true | |
end | |
specify "they are false when the current value does not match" do | |
StringFilter.new([:foo, :bar], "foo").bar?.should be_false | |
end | |
end | |
describe StringFilter, "#value" do | |
specify "is the same as the current value as a symbol" do | |
StringFilter.new([:foo, :bar], "foo").value.should == :foo | |
end | |
specify "is nil when the current value is nil" do | |
StringFilter.new([:foo, :bar], nil).value.should be_nil | |
end | |
specify "is nil when the current value is the empty string" do | |
StringFilter.new([:foo, :bar], "").value.should be_nil | |
end | |
end | |
describe StringFilter, "#values" do | |
specify "lists values" do | |
StringFilter.new([:foo, :bar], "foo").values.should == [:foo, :bar] | |
end | |
end | |
describe StringFilter, "#blank_and_values" do | |
specify "lists nil and values" do | |
StringFilter.new([:foo, :bar], "foo").blank_and_values.should == [nil, :foo, :bar] | |
end | |
end | |
describe StringFilter, "dynamic value methods" do | |
specify "they return a symbol of that value" do | |
StringFilter.new([:foo], nil).foo.should == :foo | |
end | |
end | |
describe StringFilter, "#blank" do | |
it "returns nil" do | |
StringFilter.new([:foo], "foo").blank.should == nil | |
end | |
end | |
describe StringFilter, "#blank?" do | |
it "is true when the current value is nil" do | |
StringFilter.new([:foo], nil).blank?.should be_true | |
end | |
it "is true when the current value is the empty string" do | |
StringFilter.new([:foo], "").blank?.should be_true | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment