-
-
Save obie/1886393 to your computer and use it in GitHub Desktop.
def be_guest_member_of(expected) | |
Class.new do | |
def initialize(expected) | |
@expected = expected | |
end | |
def matches?(target) | |
@target = target | |
@target.memberships.where(role: "guest").map(&:network).include? @expected | |
end | |
def failure_message_for_should | |
"expected #{@target.inspect} to be a guest member of #{@expected.inspect}" | |
end | |
def failure_message_for_should_not | |
"expected #{@target.inspect} to not be a guest member of #{@expected.inspect}" | |
end | |
end.new(expected) | |
end | |
# usage example | |
user1.should be_guest_member_of network2 | |
user1.should_not be_guest_member_of network1 |
@supaspoida, methinks the more appropriate question here would be as to what is the specific benefit of that class being anonymous?
@dexterous No benefit, in fact probably harmful given the matcher DSL example provided by @sobrinho :)
@obie yeah; in fact, given that the class isn't built dynamically using the parameter to be_guest_member_of
, simply pulling the class out of the function and naming it might boost, not just performance, but also clarity of intent by at least an order of magnitude.
RSpec::Matchers also has a .define that will take care of the config stuff for you. Throw it in spec/support like so:
RSpec::Matchers.define :be_guest_member_of do |expected|
match do |target|
target.memberships.where(role: "guest").map(&:network).include? expected
end
failure_message_for_should do |target|
"expected #{target.inspect} to be a guest member of #{expected.inspect}"
end
failure_message_for_should_not do |target|
"expected #{target.inspect} to not be a guest member of #{expected.inspect}"
end
end
I would argue that this is the cleanest way to go, but make no claims regarding performance.
I do think in this case that reaching through so many associations like that is an indicator that the design should change to improve the tests though.
@obie every time you use the matcher, a new class is created and after that is instantiated.
You may want to do that:
I didn't make a benchmark but is obviously that creating a new class every time you use the matcher will be slow :)