Chaining actions?

Guys,

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?

Thanks!
Jake

On 9/11/07, Eric A. [email protected] wrote:

end

I.E. just call the methods. That will run the action and render the
template the action calls.

But you’ll lose all your action’s parameters, correct? params and
session
and the like?

Jake C. wrote:

#would it be possible to have an action that did?
def xORy
if something==true
render(:action=>:x)
else
render(:action=>:y)
end
end

How about just:

def xORy
if something == true
x
else
y
end
end

I.E. just call the methods. That will run the action and render the
template the action calls.

Eric

On 9/11/07, Jake C. [email protected] wrote:

  render(:action=>:x)

else

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
end
if !passed
x()
else
flash[:notice] = “Param check passed…we’ll continue a render
implicit
template here”
end
end

Jake C. wrote:

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.

Eric

Jake C. wrote:

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. :slight_smile: 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

Eric

Woops…typo.

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.

Thanks for your help Eric.

Jake

On 9/11/07, Eric A. [email protected] wrote:

Notice that I simplified your code a bit since blank? checks for nil?
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?

Template is missing

Missing template
script/…/config/…/app/views/my/do_something_conditionally,rhtml

So, it seems that return isn’t enough to shortcut the processing,
strangely
enough. Am I missing something?

In my test, x() is defined as:

def x
#let’s be explicit
render(:tempate=>‘my/x’)
end

tonypm wrote:

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. =)

It is a method on the Enumerable mixin provided by Ruby (not Rails).

what am I getting wrong?

My fault. I was assuming @choices was a array not a hash. If it is a
hash then you will want something like:

a.any? {|pair| pair.last.blank?}

I believe when any? is called on an hash each pair will be converted to
a two element array so pair.last will give you the value in the pair.

Eric

Eric

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

Tonypm

Eric,

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

but

a.any?(&:blank?)
gives: false

what am I getting wrong?

Thanks
Tonypm