Ruby Code Not Getting Result

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 stuff

How 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:

  1. 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)
  2. 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



Leave a reply



Submit