26

I need to render another controller action <%= render "controller/index" %> and i get this error

Missing partial controller/index with {:formats=>[:html], :locale=>[:en, :en], :handlers=>[:rjs, :rhtml, :rxml, :erb, :builder]} in view paths "/path_to/app/views"

how can i render another controller action into a view but without sending an redirect to the client ? I've tried

<%=render :action => "index", :controller=>"controller" %>

but it seems that is not working.

Camilo Martinez
  • 1,723
  • 2
  • 21
  • 26
Mihai
  • 1,254
  • 2
  • 15
  • 27

5 Answers5

30

Try to render template:

<%= render :template => "controller/index" %> 

Or file:

<%= render :template => "#{Rails.root}/app/controllers/controller/index" %> 

And I believe you should render it through controller, as far as it is more convenient:

def your_action
  ...
  render :action => :index
end
Stephen Byrne
  • 7,400
  • 1
  • 31
  • 51
fl00r
  • 82,987
  • 33
  • 217
  • 237
  • I've try to use render :template but is rendering the html and i need to render the index method because the index method gets some data from DB needed for that view. – Mihai May 19 '11 at 07:19
  • fl00r is right, best to handle this from within the controller. Note that there's a built-in fallback, if it can't find controller/index it renders application/index. So if there are pages (not partials) which have to be rendered from different controllers, put them under app/views/application. – Yorick Sijsling Mar 18 '13 at 20:00
21

This works well for me :

def renderActionInOtherController(controller,action,params)
  controller.class_eval{
    def params=(params); @params = params end
    def params; @params end
  }
  c = controller.new
  c.request = @_request
  c.response = @_response
  c.params = params
  c.send(action)
  c.response.body
end

then, call by

render :text => renderActionInOtherController(OtherController,:otherAction,params)

basically it hacks the other class and overwrites its "params" method and return

If you are using Rails 4:

def renderActionInOtherController(controller,action,params)
    c = controller.new
    c.params = params
    c.dispatch(action, request)
    c.response.body
end
James
  • 697
  • 5
  • 23
gene tsai
  • 432
  • 3
  • 3
20

From Rails Guides page:

Using render with :action is a frequent source of confusion for Rails newcomers. The specified action is used to determine which view to render, but Rails does not run any of the code for that action in the controller. Any instance variables that you require in the view must be set up in the current action before calling render.

So in short you can't render another action, you can only render another template. You could get the shared code and move it to a method in application controller. You could also try something along this lines if you really can't structure your code in some other way:

# This is a hack, I'm not even sure that it will work and it will probably
# mess up your filters (like ignore them).
other_controller = OtherController.new
other_controller.request = @_request
other_controller.some_action
Marek Sapota
  • 20,103
  • 3
  • 34
  • 47
0

If you do not want just to render the view of the other controller (/model), but calling the action (method), think more the ruby way of life - put this method(s) into a module and include it in the controllers you need it.

I think its less 'spooky' then somehow touching an other controller.

module StandardActions
    def show_user_homepage(local_params=params)
        #something finding 
        #something to check
        render :"homepage/show" 
    def
end

class AddressesController < ApplicationController
    include StandardActions

    def update
        # update address
        if ok
            show_user_homepage(id: user_id)
        else
            #errorthings
            render :edit #(eg.)
        end
    end         
end

class HobbiesController  < ApplicationController
    include StandardActions

    def update      
        # update hobby
        if ok
            show_user_homepage(id: user_id)
        else
            #errorthings
            render :edit #(eg.)
        end
    end         
end
halfbit
  • 3,773
  • 2
  • 34
  • 47
0

Rendering partials of another controller is no problem.
So why not moving the original action view to a partial and render this partial wherever you need it:

move app/views/controller_a/index.html.erb to app/views/controller_a/_index.html.erb .

app/views/controller_a/index.html.erb:

<%= render partial: 'index' %>

app/view/controller_b/some_action.html.erb:

<%= render partial: 'controller_a/index' %>
Martin M
  • 8,430
  • 2
  • 35
  • 53