I'm probably missing something really obvious here. I have the following Ruby method:
def pair_array
return self.pair.each_slice(2) {
|x| puts x.join(" & ")
}.to_s
end
When I try to display the value of this method in my Rails view by calling #team.pair_array nothing appears, but the correct value gets printed on the console. I know this is probably because I'm using puts. How can I get the result of this method to display in my view?
You're confusing printing with returning a value. puts returns nil, and each_slice does not return the result of the block anyway. What you want is this:
def pair_array
pair.each_slice(2).map {|arr| arr.join ' & '}
end
Related
I was trying to DRY up a Rails controller by extracting a method that includes a guard clause to return prematurely from the controller method in the event of an error. I thought this may be possible using a to_proc, like this pure Ruby snippet:
def foo(string)
processed = method(:breaker).to_proc.call(string)
puts "This step should not be executed in the event of an error"
processed
end
def breaker(string)
begin
string.upcase!
rescue
puts "Well you messed that up, didn't you?"
return
end
string
end
My thinking was that having called to_proc on the breaker method, calling the early return statement in the rescue clause should escape the execution of foo. However, it didn't work:
2.4.0 :033 > foo('bar')
This step should not be executed in the event of an error
=> "BAR"
2.4.0 :034 > foo(2)
Well you messed that up, didn't you?
This step should not be executed in the event of an error
=> nil
Can anyone please
Explain why this doesn't work
Suggest a way of achieving this effect?
Thanks in advance.
EDIT: as people are wondering why the hell I would want to do this, the context is that I'm trying to DRY up the create and update methods in a Rails controller. (I'm trying to be agressive about it as both methods are about 60 LoC. Yuck.) Both methods feature a block like this:
some_var = nil
if (some complicated condition)
# do some stuff
some_var = computed_value
elsif (some marginally less complicated condition)
#error_msg = 'This message is the same in both actions.'
render partial: "show_user_the_error" and return
# rest of controller actions ...
Hence, I wanted to extract this as a block, including the premature return from the controller action. I thought this might be achievable using a Proc, and when that didn't work I wanted to understand why (which I now do thanks to Marek Lipa).
What about
def foo(string)
processed = breaker(string)
puts "This step should not be executed in the event of an error"
processed
rescue ArgumentError
end
def breaker(string)
begin
string.upcase!
rescue
puts "Well you messed that up, didn't you?"
raise ArgumentError.new("could not call upcase! on #{string.inspect}")
end
string
end
After all this is arguably a pretty good use case for an exception.
It seems part of the confusion is that a Proc or lambda for that matter are distinctly different than a closure (block).
Even if you could convert Method#to_proc to a standard Proc e.g. Proc.new this would simply result in a LocalJumpError because the return would be invalid in this context.
You can use next to break out of a standard Proc but the result would be identical to the lambda that you have now.
The reason Method#to_proc returns a lambda is because a lambda is far more representative of a method call than a standard Proc
For Example:
def foo(string)
string
end
bar = ->(string) { string } #lambda
baz = Proc.new {|string| string }
foo
#=> ArgumentError: wrong number of arguments (given 0, expected 1)
bar.()
#=> ArgumentError: wrong number of arguments (given 0, expected 1)
baz.()
#=> nil
Since you are converting a method to a proc object I am not sure why you would also want the behavior to change as this could cause ambiguity and confusion. Please note that for this reason you can not go in the other direction either e.g. lambda(&baz) does not result in a lambda either as metioned Here.
Now that we have explained all of this and why it shouldn't really be done, it is time to remember that nothing is impossible in ruby so this would technically work:
def foo(string)
# place assignment in the guard clause
# because the empty return will result in `nil` a falsey value
return unless processed = method(:breaker).to_proc.call(string)
puts "This step should not be executed in the event of an error"
processed
end
def breaker(string)
begin
string.upcase!
rescue
puts "Well you messed that up, didn't you?"
return
end
string
end
Example
I have a problem with this fragment of code, because for some reason I can´t use the method length:
def comidayprop()
aux=""
tam=#comida.lenght
i=0
for i in (0..tam-1)
aux<<"- #{#comida[i]}#{#prop_aprox[i]}#{#prop_exact[i]}"
i+=1
aux+="\n"
end
"#{aux}"
end
Later, I use this to show the content saved in aux:
def to_s
"Menú basado en #{#tipo}:\n#{m_nombre}\n#{comidayprop}\n#{vct}\n"
end
I tried to use count and size instead of length, but they don't work.
First, you wrote lenght instead of length.
Then, the object you're calling length on is nil, which could mean it was not properly initialized or there is some missing data.
Also, you don't need to increment i with i = i+1, this is done by the for loop. By the way, using each is considered a better practice than for.
Finally, "#{aux}" is just aux when aux is already a string.
You won't be able to call size, count or anything interesting on #comida as long as it is nil.
Your code could be a bit shorter.
This one will return an empty string when #comida is nil. But should it be possible for #comida to be nil?:
def comidayprop
aux=""
(#comida || []).each_with_index do |x,i|
aux<<"- #{x}#{#prop_aprox[i]}#{#prop_exact[i]}\n"
end
aux
end
I am developing a rails app. I want to split the sentence typed in a searchbox in my app using split(" "). But I am getting undefined method `split' for nil:NilClass error. I am using form data and since the form search box data is empty during page loading,I am getting this error.
My code is:-
def string_array_conversion(sentence)
sen_array=Array.new
values = sentence.split()
values.each do |value|
sen_array.push(value)
puts value
end
puts "this is the array"
puts sen_array
return sen_array
end
Here the function parameter 'sentence' is a form data. It is in the caller method :params[pt]
The code that is calling the method is:
def new
#emp=Employee.new
#emps=Employee.all
#aut=Autocomp.new
#auts=Autocomp.all
#check=params[:pt]
puts #check
ret_sen_array=string_array_conversion(#check)
puts ret_sen_array
end
Please tell me how to solve this issue.
values = sentence.split()
Replace above line to following line.
values = if sentence.present?
sentence.split()
else
[]
end
sentence arrives nil into your method. We need the code that calls string_array_conversion
The cause of the error is value of sentence is nil. Make sure the value of sentence is not nil. You can control the exception like this,
def string_array_conversion(sentence)
return unless sentence
sen_array=Array.new
values = sentence.split()
values.each do |value|
sen_array.push(value)
puts value
end
puts "this is the array"
puts sen_array
return sen_array
end
I would take another approach to solve this problem.
In Ruby, nil responds to the method .to_s and returns an empty string (""). In addition, a string can respond to this method and returns the same string (it's an idempotent operation). So, I'll call the method .to_s of the sentence variable to ensure working with strings:
def string_array_conversion(sentence)
sen_array=Array.new
values = sentence.to_s.split()
values.each do |value|
sen_array.push(value)
puts value
end
puts "this is the array"
puts sen_array
return sen_array
end
The following code:
User.all.each {|u| puts u.id}
Prints out all the fields for all records.
How can I change it to only print the id field?
I was unable to replicate this behavior but if you are looking at this in console you may be mistaking the fact that #each returns self (and self, a big array of User objects, is then inspected) for the call to each printing all fields. Can you instead run User.all.each {|u| puts u.id}; nil to have the console return nil after the each and see if the behavior persists?
If you run puts u, does it give a hash or an object? If hash, then use puts u[:id] or puts u['id'] rather than puts u.id.
If you are running this irb or rails console, it should print out just the IDs but then the return from your code is the set of users which the console will then print out. Scroll up and you will see the output you expect followed by the print out of all the user objects with full details.
Here's a trimmed down version of my code:
Helper method:
def render_tree nodes, &block
block.call nodes[1]
return 0
end
and my HAML file:
= render_tree #sections do |node|
- logger.debug("BLOCK CALLED");
= node.title
The code should print node.title, with the method returning 0. Instead it just prints "0" (the return value).
If I comment out return 0 node.title is printed.
In both situations, the debugger prints "BLOCK CALLED".
I want to print "test" and return 0. What am I doing wrong here?
Edit: So I figure HAML is outputting whatever is returned from the method. The full example is a recursive method that prints out a bunch of stuff. How can I get it to process the HAML instead of just return it?
For starters, if you don't want to print 0(the return value), you have to change this line:
= render_tree #sections do |node|
to this line:
- render_tree #sections do |node|
I am not 100% on what you are asking yet...
But, if you want the render_tree method to process the HAML string contained in nodes[1] then you would want to do something like
def render_tree(nodes, &block)
html = Haml::Engine.new(nodes[1]).render.html_safe
block.call(html)
end
But, I don't think this will do quite what you are looking for. In part I am confused because your construction doesn't seem very "railsish."
Perhaps with a bit more context it would be clearer?