Ruby: method inexplicably overwritten and set to nil
Names on the left hand side of assignments get set to nil
, even if the code can't be reached as in the if false
case.
>> foo
NameError: undefined local variable or method `foo' for main:Object
...
>> if false
.. foo = 1
.. end #=> nil
>> foo #=> nil
When Ruby tries to resolve barewords, it first looks for local variables (there's a reference to that in the Pickaxe book, which I can't seem to find at the moment). Since you now have one called foo
it displays nil
. As Mischa noted, the method still can be called as foo()
.
Pass url params hash in controller to another method, becomes nil
The Ruby interpreter is treating params
as a local variable and initializing it with nil
when it sees the assignment. This happens before it executes the retrieve_id_if_missing
.
This is why explicitly assigning a value to the local variable before calling the method avoids the error, because the initialization to nil
by Ruby doesn't happen.
The following examples demonstrate this:
Example #1
def foo(bar)
puts "foo bar: #{bar.class}"
end
bar = foo(bar) # => nil
puts "bar: #{bar.class}"
# Outputs:
# foo bar: NilClass
# bar: bar: NilClass
Example #2
a = a # => nil
puts "a: #{a.class}"
# Outputs:
# a: NilClass
Example #3
a = 123 if a # => nil
puts "a: #{a.class}"
# Outputs:
# a: NilClass
References:
Why is a = a
nil
in Ruby?
Ruby interpreter initializes a local variable with nil when it sees an
assignment to it. It initializes the local variable before it executes
the assignment expression or even when the assignment is not reachable
(as in the example below). This means your code initializes a with nil
and then the expression a = nil will evaluate to the right hand value.a = 1 if false a.nil? # => true The first assignment expression is not
executed, but a is initialized with nil.
Ruby: method inexplicably overwritten and set to nil
Here's another example:
a = 123 if a # => nil a # => nil We shouldn't be able to say if a
because we never set a, but Ruby sees the a = 123 and initializes a,
then gets to if a at which point a is nilI'd consider it a quirk of the interpreter, really. Gary Bernhardt
makes fun of it in wat (https://www.destroyallsoftware.com/talks/wat)
with a = a
Variable declaration behavior in if clause Ruby
In ruby, the variables declared inside the if
block have the exact same scope as the variables which are declared at the top level inside a method. Since the interpreter has gone through the line where it has seen bar
, its fine with it.
What does the equal ('=') symbol do when put after the method name in a method definition?
That snippet defines a Virtual Attribute (or a "setter" method) so that "express_token" looks like an attribute, even though it's just the name of the method. For example:
class Foo
def foo=(x)
puts "OK: x=#{x}"
end
end
f = Foo.new
f.foo = 123 # => 123
# OK: x=123
Note that the object "f" has no attribute or instance variable named "foo" (nor does it need one), so the "foo=" method is just syntactic sugar for allowing a method call that looks like an assignment. Note also that such setter methods always return their argument, regardless of any return
statement or final value.
If you're defining a top-level setter method, for example, in "irb", then the behavior may be a little confusing because of the implicit addition of methods to the Object class. For example:
def bar=(y)
puts "OK: y=#{y}"
end
bar = 123 # => 123, sets the variable "bar".
bar # => 123
Object.new.bar = 123 # => 123, calls our method
# OK: y=123
Object.public_methods.grep /bar/ # => ["bar="]
Rspec: object isn't receiving method call from class method test
The problem is that you set expectation on one user, but method call happens on another user. This one.
user = from_token token
You didn't show implementation of from_token
, but I'm willing to bet that it loads user from database. Now, there may be only one user in the database and, logically, these two variables represent the same entity. But physically, they're still two different objects in memory. So, naturally, the expectation is not met.
rspec not_to change from not behaving as expected
I don't think it does quite what you expect, but the way the tests are written doesn't really expose this. Your last value fails because it was never defined as 1.
The main step in revealing this is inverting the test.
describe "stuff" do
it "should not change i" do
i = 0
expect {
i = 2
}.to change { i }
end
it "should not change i" do
i = 0
expect {
i = 2
}.to change { i }.from( 0 )
end
it "should not change i" do
i = 0
expect {
i = 2
}.to change { i }.from( 1 )
end
end
This results in the first two tests passing, and the last test failing with the error result should have initially been 1, but was 0
So if we take the problem test as it was, you are saying is i should not change from 1
and since i is never 1, this test will never fail.
it "should not change i" do
i = 0
expect {
i = 2
}.not_to change { i }.from( 1 ) # i goes from 0 to 2, not 1 to 2, so the test is valid
end
How can I run PHP script in certain interval (e.g. once a day)?
If you can't or don't want to use use cron and it's ok to update it only when the page is accessed. You could cache the result of the HTTP request and only update it on a page load it if the cache is older than a day or whatever interval you choose.
Related Topics
Rails Force Ssl Only on Specified Controllers
Ruby on Linux Pty Goes Away Without Eof, Raises Errno::Eio
Ruby: Building a Plot of Function
How to Check If a String Has at Least One Number in It Using Ruby
Mismatched Bundler Version - Bundler 2, Ruby 2.6
Rails Fastercsv "Unquoted Fields Do Not Allow \R or \N"
How to Create a Rails 4 Concern That Takes an Argument
Generate All "Unique" Subsets of a Set (Not a Powerset)
Cannot Start Rails Server, "No Such File to Load -- Bundler/Setup"
How to Convert Ppt to Images in Ruby
Rails: Methods Shared by Multiple Controllers
How to Split a String by Commas Except Inside Parenthesis, Using a Regular Expression
Missing File in Gem After Build
Nokogiri: Searching for <Div> Using Xpath