Forum: Ruby on Rails calling a controller/action from another controller

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Fef8f651fefa7b23683a4e57041474d2?d=identicon&s=25 Jonathan Leonard (johanatan)
on 2006-02-16 18:15
Hi,

Is there a way to call a controller/action pair from another controller
as well as render the view for that pair?  I have tried using "render
'ctrl/action'" and that works, but the controller code isn't called
(only the view is rendered).  A redirect_to isn't desirable either as I
want the resulting content to be rendered in the current controller's
layout.

I have thought of a workaround, but it seems to violate some design
principles of Rails.  That is, the put the controller code for the
actions that I need to do this with in helpers and let the action
essentially call the controller.  However, this doesn't seem like a very
elegant solution.  Is there a better way?

Thanks,
Jonathan

P.S.  I thought I read a topic along these lines before, but I can't
seem to locate it now.
132a94ca65959bda6c74fae54bff2425?d=identicon&s=25 Ezra Zygmuntowicz (Guest)
on 2006-02-16 19:11
(Received via mailing list)
On Feb 16, 2006, at 9:15 AM, Jonathan Leonard wrote:

>
> P.S.  I thought I read a topic along these lines before, but I can't
> seem to locate it now.
>


	Use render_component:

<%= render_component :controller => 'foo', :action => 'bar' %>

Cheers-
-Ezra Zygmuntowicz
Yakima Herald-Republic
WebMaster
http://yakimaherald.com
509-577-7732
ezra@yakima-herald.com
Fef8f651fefa7b23683a4e57041474d2?d=identicon&s=25 Jonathan Leonard (johanatan)
on 2006-02-16 19:34
Ezra Zygmuntowicz wrote:
> On Feb 16, 2006, at 9:15 AM, Jonathan Leonard wrote:
>
>>
>> P.S.  I thought I read a topic along these lines before, but I can't
>> seem to locate it now.
>>
>
>
> 	Use render_component:
>
> <%= render_component :controller => 'foo', :action => 'bar' %>
>

Thanks for the response.

But, this looks like view code.  I'm trying to do this from the
controller.  (The reason I can't use the view is I have an action called
'menu' in my controller which handles menu hits (it can be one of many
different actions).

I tried calling render_component from the controller, but that was
basically the same as a redirect_to (i.e., it didn't preserve the
current controller's layout. I even tried adding :layout =>
'currentController' to the render_component call.  Am I missing
something?

--J
132a94ca65959bda6c74fae54bff2425?d=identicon&s=25 Ezra Zygmuntowicz (Guest)
on 2006-02-16 20:06
(Received via mailing list)
On Feb 16, 2006, at 10:34 AM, Jonathan Leonard wrote:

>>
>
> I tried calling render_component from the controller, but that was
> basically the same as a redirect_to (i.e., it didn't preserve the
> current controller's layout. I even tried adding :layout =>
> 'currentController' to the render_component call.  Am I missing
> something?
>
> --J
>

Yes you need to set a flag in the render component call to tell the
other controllers action to render without layout:


render_component :controller => 'foo', :action -> 'bar', :no_layout
=> true


Then in the other controller action you check for the flag and render
without a layout if its present:

def bar
   # do stuff you need
   if params[:no_layout]
      render :layout => false && return
   end
   # do the normal render however you like
end

Hope that helps

-Ezra Zygmuntowicz
Yakima Herald-Republic
WebMaster
http://yakimaherald.com
509-577-7732
ezra@yakima-herald.com
Fef8f651fefa7b23683a4e57041474d2?d=identicon&s=25 Jonathan Leonard (johanatan)
on 2006-02-16 23:16
Ezra Zygmuntowicz wrote:
>
> Yes you need to set a flag in the render component call to tell the
> other controllers action to render without layout:
>
>
> render_component :controller => 'foo', :action -> 'bar', :no_layout
> => true
>

I think you meant:

render_component :controller => 'foo', :action => 'bar', :params => {
"no_layout" => true }

>
> Then in the other controller action you check for the flag and render
> without a layout if its present:
>
> def bar
>    # do stuff you need
>    if params[:no_layout]
>       render :layout => false && return
>    end
>    # do the normal render however you like
> end
>

Ok.  This actually worked (but didn't produce the intended result).  It
just removed all formatting (i.e., style).

So, I changed the above code slightly to be :params => { 'layout' =>
'theDesiredLayout' } and set :layout = params['layout'] in the call to
render.  This brought back the style that was there previously (the
scaffold stylesheet), but still didn't display the content in the proper
layout (i.e., the calling controller's layout).

--J
132a94ca65959bda6c74fae54bff2425?d=identicon&s=25 Ezra Zygmuntowicz (Guest)
on 2006-02-17 00:23
(Received via mailing list)
On Feb 16, 2006, at 2:16 PM, Jonathan Leonard wrote:

> I think you meant:
>
> render_component :controller => 'foo', :action => 'bar', :params => {
> "no_layout" => true }
>

Ahh yes, you are right. I was just typing it and didn't test anything ;)

>> end
> proper
> layout (i.e., the calling controller's layout).
>
> --J

What exactly are you wanting to do? I guess I don't understand. If
you want to render the action from another controller in the current
controller/actions view and layout you do need layout false in the
component that gets rendered.


-Ezra Zygmuntowicz
Yakima Herald-Republic
WebMaster
http://yakimaherald.com
509-577-7732
ezra@yakima-herald.com
Fef8f651fefa7b23683a4e57041474d2?d=identicon&s=25 Jonathan Leonard (johanatan)
on 2006-02-17 00:40
Ezra Zygmuntowicz wrote:

> What exactly are you wanting to do? I guess I don't understand. If
> you want to render the action from another controller in the current
> controller/actions view and layout you do need layout false in the
> component that gets rendered.
>
>

Yea, that's it.  I want to display the result of another
controller/action in the current controller's layout/view.  I've tried
render_component with :layout => false and :layout => 'callingCtrl'.
:layout => false yielded a page with no style at all (as expected) and
:layout => 'callingCtrl' yielded the same page I would've gotten from a
redirect_to (except the address remained in the calling controller) or a
render_component with no layout clause.

BTW, doing this:

render 'ctrlr/action'

renders the page embedded in the current layout like I want, but that
doesn't actually call the controller code.  So, if I wanted to use this
approach, I'd either have to duplicate the controller code in the
calling controller or put that code in a helper and call it from the
view (or is there another way?? such as a controller helper, or a way to
directly call something like this:

class CallingController
  def foo
    CalledController.action
    render 'ctrlr/action'
  end
end

I know that won't work because the action is an instance method instead
of a class method.  Is there an instance of each controller lying around
somewhere?

--Jonathan
Fef8f651fefa7b23683a4e57041474d2?d=identicon&s=25 Jonathan Leonard (johanatan)
on 2006-02-17 00:44
Jonathan Leonard wrote:

> I know that won't work because the action is an instance method instead
> of a class method.  Is there an instance of each controller lying around
> somewhere?
>


I just thought of something that should work.  I could put the
functionality that's currently in the called controller in
application.rb and call it from both the calling controller as well as
the called controller and use the render 'ctrlr/action' approach that
works.  Is this the best way?

Thanks,
Jonathan
132a94ca65959bda6c74fae54bff2425?d=identicon&s=25 Ezra Zygmuntowicz (Guest)
on 2006-02-17 00:57
(Received via mailing list)
On Feb 16, 2006, at 3:44 PM, Jonathan Leonard wrote:

> I just thought of something that should work.  I could put the
> functionality that's currently in the called controller in
> application.rb and call it from both the calling controller as well as
> the called controller and use the render 'ctrlr/action' approach that
> works.  Is this the best way?
>
> Thanks,
> Jonathan
>


Well it might not belong in the controller at all. I usually use
render_component in my views to encapsulate sidebars and other
sections from other controllers into the view. But in any regard
render_component shouldn't take the layout => false , that goes in
the other controller/action being called. you need to conditionally
decide to render without layout so you just get the content and view
to render into your current state.

	But yeah you can refactor shared actions into your application
controller if that works in this particular case.

-Ezra Zygmuntowicz
Yakima Herald-Republic
WebMaster
http://yakimaherald.com
509-577-7732
ezra@yakima-herald.com
Fef8f651fefa7b23683a4e57041474d2?d=identicon&s=25 Jonathan Leonard (johanatan)
on 2006-02-17 05:04
Ezra Zygmuntowicz wrote:
>
> Well it might not belong in the controller at all. I usually use
> render_component in my views to encapsulate sidebars and other
> sections from other controllers into the view. But in any regard
> render_component shouldn't take the layout => false , that goes in
> the other controller/action being called. you need to conditionally
> decide to render without layout so you just get the content and view
> to render into your current state.
>

Oops, I meant to say 'render' there instead of 'render_component.'  That
is what I was actually doing and it still didn't get the current layout.


> 	But yeah you can refactor shared actions into your application
> controller if that works in this particular case.

Yea, that makes sense.

Thanks for the help.
Jonathan
This topic is locked and can not be replied to.