-
-
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
endI 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 :)