Ruby code not getting result
Yes, change it to
age = gets.to_i
Kernel#gets
gives a string, you need to convert it to integer to do the integer comparisons. Read String#to_i
method too.
How should I handle a conditional in Ruby where the test could result in an error?
You can just use the safe navigation operator which was introduced to Ruby in 2.3:
def author_name
author&.name
end
Note that self
is not needed in your example.
Or when you are on Ruby on Rails then you might want to use delegate
:
delegate :name, to: :author, prefix: true, allow_nil: true
Ruby Code not being executed
The call to exec
inside checkout
replaces the current process with one for the program being executed. Hence, exec
never returns. See the docs for more detail.
You can replace exec
with spawn
to enable you to execute a process separate from your controlling process. Calling spawn
will return the pid of the new process that you can then monitor using Process
.
Ruby Code not in Any Method
Methods like attr_accessor
and has_many
are often called "mimic methods" because they kinda look like ruby keywords (mimic them) but they're in fact, as you and others have correctly pointed out, method calls.
dd = DooDad.new
dd.foo
outputs nil, and never spits out any
puts
stuffHow exactly does all that work?
When you're inside of a class definition the implicit receiver of all method calls and "variable definitions" is self
, which in your case is DooDad
.
So when you're writing
class DooDad
@foo = 1
end
you're actually defining an instance variable on self
, that happens to be the class itself , since you're inside of that classes definition. (and outside of any other class, module or method definitions)
The method attr_accessor
on the other hand generates, with some help of metaprogramming, accessor methods for an instance variable of the objects that are instantiated from class DooDad
.
Back to your example:
class DooDad
attr_accessor :foo
puts "I happened!"
@foo = 7
end
With the stuff mentioned above, you should now understand that you're dealing with two different @foo variables, one for instances of class DooDad (i.e DooDad.new
), the other (the one you created by writing @foo = 7
) for the class DooDad itself!
When calling the new
method on a class, you create an instance of it.
dd = DooDad.new
#=> dd is now an object of class DooDad
dd.foo
#=> You just called the "getter" method for an instance variable foo of object dd, which was never defined before, that's why it's returning nil.
The puts "I happened!"
statement, just as the other two in fact, gets evaluated as soon as the class is loaded, but not when you call new
on it.
If you want the behaviour you described (doing stuff when calling new
), I suggest implementing an initialize()
method for DooDad
, which will get called when you call new
:
class DooDad
attr_accessor :foo
def initialize()
puts "I happened!"
@foo = 7
end
end
dd = DooDad.new
#=> outputs "I happened!" and sets dd.foo = 7
dd.foo
#=> 7
But why does @foo = 7
now set the instance variable of dd
and not DooDad
?
When you define a method with the keyword def
, you enter a new scope (you pass a scope gate). self
is now no longer the class, but instead an instance of that class, that you created with new
, just like dd
. So when you're writing @foo = 7
inside of a method definition, you're talking about variables for an instance of class DooDad
, not the class itself.
This post is probably way too long and might not even satisfy as an answer, but I hope it was somewhat comprehensive.
Why doesn't this example ruby code print the result?
Local variable movie_ratings
is not accessible in the method good_movies
. Several approaches are available here:
Pass ratings as a parameter
movie_ratings = {
memento: 3,
primer: 3.5,
the_matrix: 5,
truman_show: 4,
red_dawn: 1.5,
skyfall: 4,
alex_cross: 2,
uhf: 1,
lion_king: 3.5
}
def good_movies(ratings)
puts ratings.select {|movies, ratings| ratings > 3}
end
good_movies(movie_ratings)Make ratings instance variable (instead of local variable)
@movie_ratings = {
memento: 3,
primer: 3.5,
the_matrix: 5,
truman_show: 4,
red_dawn: 1.5,
skyfall: 4,
alex_cross: 2,
uhf: 1,
lion_king: 3.5
}
def good_movies
puts @movie_ratings.select {|movies, ratings| ratings > 3}
end
good_movies
Why doesn't this ruby code do anything?
I'm not sure what you're expecting, but if I paste your code into irb
it does in fact do something.
> multiples(1000)
233168
If you are running your code as a command-line Ruby script, then perhaps you want to print this value so you can see the result on the console? In that case you want to use puts
:
puts multiples(1000)
Case code in Ruby program not working with a passed value
You need to drop the number.to_i
from the case statement.
Or do something like
case number.to_i
when 1..2
puts "foo"
when 3..100
puts "bar"
else
puts "foobar"
end
end
From the Ruby docs
Case statements consist of an optional condition, which is in the position of an argument to case, and zero or more when clauses. The first when clause to match the condition (or to evaluate to Boolean truth, if the condition is null) “wins”, and its code stanza is executed. The value of the case statement is the value of the successful when clause, or nil if there is no such clause.
Your version would evaluate to somehting like
if (number > 1) === number.to_i
and since you are comparing a number with a boolean expression this will not evaluate to true. If you had an else in the case statement this would have been called.
How should I resolve this error? I have a problem with ruby variables
Remove the finalresult ==
parts from when
and use =
instead of ==
to assign $result
:
case finalresult
when 0..399
$result = "E"
when 400..499
$result = "D"
when 500..549
$result = "C-"
# ...
end
You might also want to replace $result
with result
, i.e. use a local variable instead of a global variable.
You might consider moving the case
statement into a method:
def grade(value)
case value
when 0..399 then "E"
when 400..499 then "D"
when 500..549 then "C-"
# ...
end
end
Get value into Ruby code block without it being the last statement
You can implicitly return values using instance variables, like it is done in Rails:
def bar
yield
puts "The block has assigned @value to #{@value}"
end
bar do
@value = 42
nil # Do not return value intentionally
end
This code outputs:
The block has assigned @value to 42
UPDATE
Another nice option is to use helper methods, many frameworks do it too:
def bar
def render(value)
@value = value
end
yield
puts "The block has rendered #{@value}"
end
bar do
render 42
nil # Do not return value intentionally
end
This code outputs:
The block has rendered 42
UPDATE 2
Please see an important addition from @Marek Lipka https://stackoverflow.com/a/19542149/203174
Related Topics
Error Loading the 'Sqlite3' Active Record Adapter. When I Deploy in Heroku
How to Return a Group of Sequential Numbers That Might Exist in an Array
How to Sign Out in a Rails App, Using Devise Gem, No Route Matches /Users/Sign_Out
Ruby: Sorting 2 Arrays Using Values from One of Them
Sending Form Data to Remote Rails Application Using Httparty
How to Properly Create a Associated Record Just After the Associator Record Creation
Ruby Roo Loaderror: Cannot Load Such File -- Spreadsheet/Note
How to Send Notifications to the User Whose Post Received a Comment
Undefined Method 'Click' for Nil:Nilclass (Mechanize)
How to Ignore Irrelevant Methods When Profiling Ruby Applications
What Is the Fully Qualified Name of a Model in Ruby on Rails
How to Mimic Browser X509 Client Certificate Verification Without Access to Http Layer
Sinatra Doesn't Know This Ditty Even When Default Route Is Implemented with Modular Style
Does Will Pagination Work with Forms Which Have Method="Post"
Invalid Route Name, Already in Use: 'Admin_Root' (Argumenterror) - Failed Activeadmin Install