I have created a haml-partial which I want to use as a default header. When rendering this out I optionally want to give it a block to replace a part of the default content.
I've tried multiple things:
render partial: "partial", capture: do
# Don't really know why I tried this, Syntax error ofcourse.
render partial: "partial" do
# 'nil' is not an ActiveModel-compatible object. It must implement :to_partial_path.
render layout: "partial" do
# Works, but:
render layout: "partial"
# You invoked render but did not give any of :partial, :template, :inline, :file or :text option.
# So, it always needs the block
Any other options I don't know of?
Use render layout: "" when you need a block.
Use render partial: "" when you don't use a block.
They both work with locals and look for a pre-underscored file.
Related
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}"
Is it possible to specify a layout for rendering JSON in Rails 3.1+ (not that I found any easy way to do it in any previous version of Rails)?
I've been using a helper like this:
def render_as_json(obj, status = 200, *args)
render(inline: obj.to_json(*args), layout: 'default', status: status)
end
It doesn't seem like render json: obj will render a layout.
I just wanted to have some metadata in the layout file:
<%- #content = yield -%>
{
"data":<%= #content.present? ? raw(#content) : '{}' %>,
"metadata":<%= raw(json_layout_metadata.to_json) %>
}
I know this is old now but I was trying to use a JSON layout and an XML layout and while searching I found your question and it helped me somehow solve my problem so here is what I did for the JSON part and the XML is pretty much the same:
Create a template file in the layout folder in your application(in the same directory of application.html.erb), call it anything but make its extension ".json.erb", let's assume you named it "json_layout.json.erb". Put in it whatever constant content you want to add and in the place you want to display dynamic data put a
<%= yield %>
In my case, this is my template:
{"status": <%= response.status %>,"data": <%= yield %>}
Now in your controller where you want to display JSON use the following format in the respond_to block:
format.json { render :inline => #the_object.to_json(any_additional_options) , :layout => "json_layout.json.erb" }
Just be careful in case of XML to put in the options of the to_xml method
:skip_instruct => true
as you would probably don't need the full XML generated by default because you add your own in the layout.
It seems the render method has changed.
In the view I used to be able to do the following:
= render :layout => 'some_layout' do
some stuff to be rendered
It seems the best fix is to move the content into a partial and call the layout
= render :partial => 'some stuff to be rendered', :layout => 'some_layout'
I was just wondering if anyone had come across this and if it is a bug or an intended change?
EDIT
Rendering a block inline with a layout works. Check out the part about applying a layout to a block within any template at http://api.rubyonrails.org/classes/ActionView/Partials.html
The issue I am having is with the latest version of HAML not rendering nested render calls properly.
https://github.com/nex3/haml/issues/412
From your post, it appears you are trying to do this in a view.
Is it possible that you are confusing ActionController's render and ActionView's render? Looking # the API documentation for 2.3.8 & 3.x, it doesn't seem there was ever a :layout option within ActionView's render.
UPDATE
Actually, I may have been off-base. It does seem that there is an :inline option as described here.
render(options = {}, locals = {}, &block)
Returns the result of a
render that’s dictated by the options hash. The primary options are:
:partial - See ActionView::Partials.
:update - Calls update_page with the block given.
:file - Renders an explicit template file (this used to be the old default), add :locals to pass in those.
:inline - Renders an inline template similar to how it’s done in the controller.
:text - Renders the text passed in out.
This is fixed in the most recent version of HAML v3.1.3
I want to use partials in rails along with single-table inheritance. I currently have this working:
render partial: #vehicle
# which renders the relevant view, depending on object type, eg:
# views/trucks/_truck.haml
# views/car/_car.haml
I want to leave these default views in place, and create an additional compact view for each object, perhaps like this
# example code only, I want to write something like:
render partial: 'compact', locals: {vehicle: #vehicle}
# and then have this render (for example) with
# views/trucks/_compact.haml
# views/car/_compact.haml
I can happily rename things or change the file names or locations, but what is the simplest way to support two kinds of views (compact and default)?
There will be many more classes later, so looking for very clean, elegant code.
(rails 3.0.5+ on ruby 1.9.2)
To get exactly what you asked for you should do this:
render partial: "#{#vehicle.type.tableize}/#{#vehicle.type.underscore}", object: #vehicle
and you will get rendered:
views/trucks/_truck.html.haml
and the object will be accessible as:
#truck
There might be a better way, but there is always this approach:
render partial: "#{#vehicle.class.to_s.tableize}/compact", locals:{vehicle: #vehicle}
(or it might need to be _compact, instead of just compact, but you get the idea)
I've done something similar, but rather than having the partials in two separate files, I've combined them, and used the locals argument to pass a flag:
# The hash syntax for render is redundant, you can simply pass your instance
# Render the long-form of your partial
render #vehicle
# When using render _instance_, the second argument becomes the locals declaration
# Render the compact form
render #vehicle, compact: true
And then, in my partial...
<% if defined? compact %>
<!-- HTML for compact view -->
<% else %>
<!-- HTML for extended view -->
<% end %>
The advantages of this approach are that you're only maintaining one partial file for each vehicle type, and your code remains pristine.
The disadvantage is that it's a slight departure from the "traditional" usage of partials.
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] %>