Grails has the concept of chaining actions. Is it possible to do the same within Rails?
In other words, if I had the following:
class MyController < ApplicationController
def x
render (:template=>‘x’)
end
def y
render(:template=>‘y’)
end
#would it be possible to have an action that did?
def xORy
if something==true
render(:action=>:x)
else
render(:action=>:y)
end
end
end
Note, render(:action) is just my idea of how it might work…I’m not implying that it’s valid syntax.
If this is not something readily available in Rails, what do you do to emulate? Surely it’s a common pattern to need to “chain” a sequence of action calls?
Also, I find that in a more complex example, this makes like difficult and forces you to be more explicit:
Let’s say I’m using the implicit template rendering in x and y. Calling x or y will break down in this case…you have to explicitly call render(:template=“controllername/x”) if you call x() as a method.
Also, let’s say we have a method like this:
def do_something_conditionally
@choices = params[:choices]
@choices.each do |one_choice|
if one_choice.nil? or one_choice.empty?
x()
end
end
flash[:notice] = “Param check passed…we’ll continue a render implicit template here”
end
This won’t work because, because even though you call x(), the processing of the rest of the logic doesn’t stop. So, you’d have to do something like:
def do_something_conditionally
@choices = params[:choices]
passed = true
@choices.each do |one_choice|
if one_choice.nil? or one_choice.empty?
passed=false
break
end
But you'll lose all your action's parameters, correct? params and session and the like?
Nope. params and the like are methods on the ActionController::Base object and therefore are still available when you are calling another method in the same object your action is defined in.
def do_something_conditionally
@choices = params[:choices]
@choices.each do |one_choice|
if one_choice.nil? or one_choice.empty?
x()
end
end
flash[:notice] = "Param check passed...we'll continue a render implicit template here"
end
This won't work because, because even though you call x(), the processing of the rest of the logic doesn't stop.
Of course the method you call returns and execution continues. That's just the way methods work. But if you want to exit early just return. So:
def do_something_conditionally
@choices = params[:choices]
x and return if @choices && @choices.any?(&:blank?)
flash[:notice] = "Param check passed..."
end
Notice that I simplified your code a bit since blank? checks for nil? and empty? and I used any? to process the loop. But if you prefer your more verbose method you can do the same thing:
def do_something_conditionally
@choices = params[:choices]
@choices.each do |one_choice|
if one_choice.nil? or one_choice.empty?
x
return
end
end
flash[:notice] = "Param check passed..."
end
Well, first off, nice code. I love the terseness (esp the symbol#to_proc). Very clean.
I had actually thought before that this should work, but it didn’t for me. After seeing your example I have tried it both ways, to no avail. The error I get?
Ok, so your version works, but only as long as you explicitly render “something” in the controller you’re calling as a method. In other words, if I don’t define render in x(), it won’t work. I presume it has something to do with the backend code rails uses to support explicit templates.
def do_something_conditionally
@choices = params[:choices]
x and return if @choices && @choices.any?(&:blank?)
flash[:notice] = "Param check passed..."
end
OK - I give up, where did any? come from. Cant find it in the Ruby
manual, cant find it in the Rails doc and certainly cant find it by
googling. =)
Also, am I missing something cos I cant make it work?
If I have a hash {:a=>1, :b=>2, :c=>nil}
a.each {|k,v| puts v.blank?}
gives: false, false, true
Thanks Eric, I should have thought about it being for an array - me
being a bit dim.
I often wonder how many useful methods are around that I don't know
about. This group is very useful for picking up tidbits like that -
it's remembering them or knowing how to cross reference them that is
difficult. (I'm getting on a bit you see and the old grey matter
dosn't retain stuff like it used to. sometimes I just struggle to
remember where I saw something, let alone the detail of what it does.
Oh well at least we have google (except for common expressions like
any? that is.)