Specify namespace when using "render" with an object in rails 3 - ruby-on-rails

So, you can do something like that in rails:
#features.each do |feature|
render feature
end
and it will look for a partial called _feature.html.erb in the views/features folder, based on the class name.
But what if features are in a cms namespace?
Is it possible to specify the namespace? Doing something like this (it doesnt work, obviously)
render [:cms, feature]
Thx

You'll have to be more explicit:
render :partial => '/cms/feature', :object => feature
This will render the 'app/views/cms/_feature.html.erb' partial with the object being 'feature'.

Related

Rails: Rendering a Namespaced Polymorphic Partial

I have a polymorphic model called Update. Typically, I can render its associated updatable model with a simple:
<%= render #update.updatable %>
Unfortunately, if I'm calling this method from within a namespaced controller, then Rails will try to namespace the view path as well, searching admin/reviews/review rather than reviews/review. This results in errors like:
Missing partial admin/reviews/review
Typically I can hardcode a workaround, such as:
<%= render :partial => "/reviews/review", :locals => {:review => #update.updatable}
This would be fine if the association weren't polymorphic, but since it is, I'll get errors if the updatable is anything other than a Review. Unfortunately, I have dozens of possible updatables, and branching through them with a case statement would be troublesome to maintain.
Is there a simpler approach I'm not thinking of?
You can define the partial path from your models. It is something like this:
class Review
def to_partial_path
"/reviews/review"
end
end

render partial of another namespace

I have a problem. I need to render objects using partials of another namespace.
render complain.target
it tryes to render partial from current namespace(current is admin)
Missing partial admin/bulletins/bulletin...
I dont need to render it from admin/..
I cant specify partial path like
render partial: '/bulletins/bulletin', locals: { bulletin: complain.target }
But it's polymorphic association, and different partial pathes are used.
Is it any way to do it?
Thanks in advance!
There seems to be no possible way to achieve this with a render complain.target call (Checked on Rails 5 source).
There is a config option for action_view to disable namespace prepending for partials, though:
Rails.application.config.action_view.prefix_partial_path_with_controller_namespace = false
EDIT
Today, I've used another solution:
When rendering Single-Table-Inheritance models into partials, one can pass the locals variable name based on the Rails model_name lookup, when calling the render partial:
<%= render partial: "admin/#{object.to_partial_path}",
locals: { object.model_name.element => object }
%>
You can use render "/#{complain.target.to_partial_path}"

Rails implicit render in templates from multiple controllers

I have code like render #posts to render my posts collection in an index template which the PostsController renders.
Now I have an Admin::PostsController that also should render the collection but when my posts controller renders #posts it looks for the admin/posts/_post.html.erb partial. Do I now have to write the partial path explicity? Is this feature by design or a bug? It doesn't seem to make sense.
Yes, you need to supply the path explicitly. And yes, this is by design.
It actually makes sense because Rails is a MVC framework and if you create a controller under a different namespace one would expect separate views for that controller too. Think about convenience, if you wanted to quickly bootstrap an application with a few simple commands, an application where there's a public view of posts and an admin view where all of the admin goodies for editing are, you would EXPECT to have a different directory to store all that admin views.
render #posts is a shortcut for a longer method signature.
In case of PostsController, it is a short cut for render :partial => "post", :collection => #posts; the partial is _post.html.erb and it is expected to be in app/views/posts folder.
In case of Admin::PostsController, it is a short cut for render :partial => "admin#post/post", :collection => #posts; the partial is _post.html.erb, and it is expected to be in app/views/admin/posts folder.
If you want a different partial to be used, you should specify it explicitly.
See the Rendering Collections section of Rails Guides page on Layouts & Rendering for detailed explanation.

Including a partial "as is" in Ruby on Rails

I am using stache for server-side evaluation of Mustache templates. I would like to re-use some of these templates on the client-side from JavaScript using ICanHaz.js, but to do so I need to include them into script tags. I would like to avoid duplicating the templates (DRY), but obviously, the templates must not be evaluated before being sent to the client, so using a simple render :partial invocation like in this (HAML) snippet does not work:
%script{:id => 'project_snippet'}
= render :partial => 'project'
Is there any way to include a partial without evaluating it using the underlying template engine (kind of like a raw include)?
In other places the partial is to be used as regular partial, i.e., evaluation is supposed to happen, so changing the file extension to always avoid evaluation is not an option.
do you need a partial as is or you want it to be rendered as HTML with some placeholders for JavaScript templating? you can pass :locals => { ... } with something to be replaced by JS template engine later i.e.
%script{:id => 'project_snippet'}
= render :partial => 'project', :locals => {:name => '{{{ project_name }}}'}
if as is then read the partial content (but it doesn't look like you want this)
%script{:id => 'project_snippet'}
= File.open("#{path/to}/partial.html.haml", "r").read
Well, it seems that I should have read the stache documentation: There is a tag helper available, so
= template_include_tag 'projects/project'
will do the trick after setting the template base directory in an initializer:
Stache.configure do |c|
c.template_base_path = "#{Rails.root}/app/views"
end

How to use partial in views with different alias MIME?

Im using 2 different sets of views for 2 different user's roles.
Im using register_alias :
Mime::Type.register_alias "text/html", :basic
in the controller:
class SomeController < ApplicationController
def index
# …
respond_to do |format|
format.html # index.html.erb (advance)
format.basic # index.basic.erb
end
end
end
In some case I have to use the same code in both views, then I would use a Partial, but because of the MIME alias, I have to use 2 identical partials:
my_partial.html.erb and my_partial.basic.erb
I think there is a solution to DRY the code and use only a partial.
Do you have some solutions ?
thank you,
Alessandro
Old Answer:
I probably tried 50 different things until I figured out the right way of writing the partial once, but it was worth it because it's super simple:
Inside your index view, you normally do:
<%= render "my_partial" %>
This implicitly gets mapped to the partial corresponding to the Mime you requested, so it implies having two partial implementations. If you want a DRY partial, simply explicitly specify the format:
<%= render "my_partial.html" %>
As an added bonus of this observation, if your responds_to block of code is really just to switch based on the format and has no logic inside it, you can entirely remove that block of code and things still work implicitly.
Rails 3.2 update:
Rails has deprecated support for the above and support has been completely removed in the latest version of Rails. The following is the correct way as of Rails 3.2:
<%= render :partial => "my_partial", :formats => [:html] %>

Resources