40

I have QuestionController I now have AnotherQuestionController with actions which should render using templates and partials in app/views/question/ Is this possible? Seems like it should be.

I've tried

render :template => "question/answer"

but answer.html.erb includes partials and I get errors like

"Missing template another_question/_my_partial.erb in view path"

So is there a way to tell Rails "treat AnotherQuestionController as if its QuestionController and look for views and partials in app/views/question"? Or will I have to create app/views/another_question - which will cause duplication (this can't be the Rails way).

Thanks

Paul
  • 981
  • 2
  • 11
  • 18

4 Answers4

60

Template rendering should actually work

 render :template => "question/answer"

The problem you were having is from the partials looking in the wrong place. The fix is simple, just make your partials absolute in any shared templates. For example, question/answer.html.erb should have

<%= render :partial => 'question/some_partial' %>

rather than the usual

<%= render :partial => 'some_partial' %> 
Ben Hughes
  • 13,521
  • 1
  • 38
  • 34
  • Any new way of doing this in rails 3.x? I'm asking because I'm using a gem which gives helpers to automatically do the rendering in the view (otherwise your solution would work). I would rather not overwrite the that gem's helpers. Thanks! – montrealmike Oct 28 '11 at 15:22
14

You can achieve it with:

render 'question/answer'
John Topley
  • 107,187
  • 45
  • 188
  • 235
klew
  • 14,349
  • 7
  • 45
  • 59
1

Rails uses a list of prefixes to resolve templates and partials. While you can explicitly specify a prefix ("question/answer"), as suggested in another answer, this approach will fail if the template itself includes unqualified references to other partials.

Assuming that you have an ApplicationController superclass, and QuestionController inherits from it, then the places Rails would look for templates are, in order, "app/views/question/" and "app/views/application/". (Actually it will also look in a series of view paths, too, but I'm glossing over that for simplicity's sake.)

Given the following:

class QuestionController < ApplicationController
end

class AnotherQuestionController < ApplicationController
end

QuestionController._prefixes
# => ["question", "application"]
AnotherQuestionController._prefixes
# => ["another_question", "application"]

Solution #1. Place the partial under "app/views/application/" instead of "app/views/question/", where it will be available to both controllers.

Solution #2. Inherit from QuestionController, if appropriate.

class AnotherQuestionController < QuestionController
end
=> nil
AnotherQuestionController._prefixes
# => ["another_question", "question", "application"]

Solution #3. Define the class method AnotherQuestionController::local_prefixes

This was added in Rails 4.2.

class AnotherQuestionController < ApplicationController
  def self.local_prefixes
    super + ['question']
  end
end
AnotherQuestionController._prefixes
# => ["another_question", "question", "application"]
Steve
  • 5,398
  • 2
  • 38
  • 39
  • Is important say: The second solution works in my context, when my action on "AnotherQuestionController" renders a view which contains partial render. Thanks! – Rafael Gomes Francisco Apr 25 '20 at 21:14
-1

You could try the inherit_views plugin (http://github.com/ianwhite/inherit_views/tree/master) I mentioned here in the answer to this question.

Community
  • 1
  • 1
Shadwell
  • 32,730
  • 14
  • 91
  • 94
  • Thanks, I'll look into this. Seems like a lot of work though doesn't it. I would have thought render() would have taken options allowing to specify another controller's views/partials. Ah well. – Paul Jun 19 '09 at 11:52