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

Jake Cutter 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

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

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 Cutter 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 Cutter wrote:

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.

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

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

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

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

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

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?

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