In RSpec, one of the techniques for providing a value to a shared example is to use let to define a variable used by that example, as described in this documentation.
Currently, the values passed into formal parameters take precedence over the any values established by let, as shown in the following example:
shared_examples_for "foo" do |x1|
specify {puts [x1, x2, x3].inspect}
end
describe "" do
let(:x1) {3}
let(:x2) {3}
let(:x3) {3}
it_behaves_like "foo", 1 do
let(:x1) {2}
let(:x2) {2}
end
end
# => [1, 2, 3]
My question is whether it would be possible/reasonable/desirable to change the RSpec semantics such that the variables set by let inside of the passed block would take precedence over the passed parameters and the above would output [2, 2, 3]. This would allow "simple" values to be passed in as parameters and more complicated values to be set via a block.
use
letto define a variable
let does not define variables; it defines a memoized helper method. The distinction is important, as ruby treats variables and methods differently. Specifically, local variables (e.g. the x1 block arg in your shared_examples_for block) always take precedence over methods of the same name, unless you use self.x1 to make it explicit that you are sending a message.
So, to answer your question: no, what you're asking is not possible. I don't think it's desirable, either; having local variables always "win" when there is a name collision is super important for being able to reason about your code. Consider the repurcssions if that was not the case. Let's say you started with this code:
# in superclass.rb
class Superclass
end
# in subclass.rb
class Subclass < Superclass
def do_something(name)
# do something with the `name` variable
end
end
At some future point, Superclass is updated to have a name method:
class Superclass
def name
"superclass name"
end
end
If ruby did not give precedence to local variables over methods, the Subclass#do_something method would get broken by an unrelated change to Superclass. The fact that local variables always take precedence means that you can more easily reason about what code does without worrying about changing in some distant code suddenly causing a particular identifier to be re-bound to a method rather than a local variable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With