Specifying format: "xml" ignored with render_to_string - ruby-on-rails

I have an action that needs to render a view to string. The view is called index.xml.erb. I am trying to achieve this with render_to_string:
my_string = render_to_string(layout: false, format: "xml")
render_to_string is instead rendering the contents of index.html.erb and assigning it to my_string. What am I missing?
Note: I am aware that I can do something like this:
my_string = render_to_string(:action => "#{self.action_name}.xml.erb")
But I'm curious as to why the "format" option isn't honored with render_to_string.

This works for me.
render_to_string( :action => "#{self.action_name}", :formats => [:xml] )

Related

render_to_string doesn't find my erb template?

I am trying to use render_to_string like this:
html_result = render_to_string(:template => 'template_160x600', layout: 'art_layout')
And I keep getting the following error:
Missing template /template_160x600
However, if I render normally, I don't have any problem:
render 'template_160x600', layout: 'art_layout'
What am I missing here?
EDITED:
I have added the view directory like this:
render 'arts/template_160x600', layout: 'art_layout'
But now I just get:
Missing template arts/show, application/show with
I believe that what is happening is that even though you are using render_to_string, Rails tries to do the default render for the show view afterwards.
So, if after render_to_string you don't want to render any view, just do this:
html_result = render_to_string(:template => 'art/template_160x600', layout: 'art_layout')
head :ok
or
html_result = render_to_string(:template => 'art/template_160x600', layout: 'art_layout')
render nothing: true
When you render a template you must specify the path from the root of the template search paths (app/views for one), so if your template is in app/views/art you would use:
html_result = render_to_string(:template => 'art/template_160x600', layout: 'art_layout')

Rails js.erb response not sending locals to Haml partial

I realize this is similar to some other questions, but I have been through a fair number of those and I think I'm doing what they suggested, but my code is still not working.
So, as the title says, I'm attempting to load a partial from a js.erb file (in response to an AJAX call.) However, it is not working correctly.
full_list.html.haml:
=link_to(test_path(#work), id: "privacy-button", remote: true) do
= render "privacy_button_content", locals: {:show_others => #work.show_others}
_privacy_button_content.html.haml:
-if locals[:show_others] == false
-test_string = "twas false"
-else
-test_string = "twas true"
%p = test_string
works_controller.rb:
def test_function
#work.model_function
respond_with(:layout => false)
end
test_function.js.erb:
$("#privacy-button").html("<%= escape_javascript render(:partial => 'privacy_button_content', locals: {:show_others => #work.show_others}) %>");
So the full_list has privacy_button, which is rendering the partial, and the response to clicking the #privacy-button should be to modify something in the controller, and get the response.js.erb.
This works correctly on page load (so passing the local to the partial does work,) but whenever I run the AJAX call I'm getting
(undefined local variable or method `locals' for #<#<Class:0x00000005006338>:0x000000068481f8>):
Any help would be appreciated.
Update _privacy_button_content.html.haml as below:
-if show_others == false
-test_string = "twas false"
-else
-test_string = "twas true"
%p = test_string
When you pass show_others in locals hash, a local variable would be created for you named show_others. You can access it as show_others in the partial and not locals[:show_others].
Refer to Passing local variables in Rails Guides.
Apply Kirti Thorat's change and then change
= render "privacy_button_content", locals: {:show_others => #work.show_others}
for
= render "privacy_button_content", show_others: #work.show_others
Also remember that views should not have logic, it should be in a helper or in a decorator
BTW: I think %p = test_string should be %p= test_string
So, I've figured it out. It seems that specific error I was getting had to do with the render syntax when working when haml (I got the same issue when I specified render :partial from the view, so it wasn't unique to the js.erb.)
The code in partial.js.erb now looks like:
$("#privacy-button").html("<%= escape_javascript render("privacy_button_content", :locals => {:show_others => #work.show_others}) %>");
As you can see, the main difference is having render "works_group_list" rather than render( partial: => "works_group_list". As I said, I believe this may be related to my views being written in Haml, though it should be noted that the render(partial:...) syntax does work when not attempting to pass local variables from a js.erb.
I was also getting some little issues because I kept referring to something as #my_element in the js when in the html it was #my-element. So if you're encountering this issue, checking your spelling (for the thirtieth time) never hurts.
Edit:
Just a note, as others have pointed out using the locals hash is not mandatory. So the line of code could instead be
$("#privacy-button").html("<%= escape_javascript render("privacy_button_content", :show_others => #work.show_others ) %>");
This will work as long as you update your partial appropriately (referring to var instead of locals[:var]).

RAILS3: to_JSON with multiple objects and includes

def list
#rings = Ring.order("RAND()")
#JSON RENDERING
render :json => #rings.to_json(:include => [:variations, :stones]), :callback => params[:callback]
end
def show
#showring = Ring.includes(:stones, :variations).find(params[:id])
#other_rings = Ring.select([:id, :stone_count]).where(:style_number => #showring.style_number).reject{ |ring| ring == #showring}
#JSON RENDERING
render :json => {#showring.to_json(:include =>[:variations, :stones]), :other_rings => #other_rings}, :callback => params[:callback]
end
My list view rendering works fine, but when i want to do a show view, with two objects, and showring with includes won't render proper JSON. It is quoting everything in the object with the includes...
JSON output looks like this:
showring => "{"available":"yes","eng...9","stone_y":"149.4"}]}"
other_rings => properly rendered object
On a seperate note, if i have already added the includes to #rings object, why do i then again have to add the association in the "to_json" method?
When you do
render :json => {:show_ring => #showring.to_json(:include =>[:variations, :stones]), :other_rings => #other_rings}
Rails is converting #showring to json (ie getting back a string representation), i.e. the value is the string literal. Instead do
render :json => {:show_ring => #showring.as_json(:include =>[:variations, :stones]), :other_rings => #other_rings}
as_json does all the work of turning the object into a hash but without the final step of turning into a string
if you are going to invest more time in building more JSON objects, you should look into a gem called rabl. It makes building JSON very simple, good for customization which then is good for building API.

Rails render html into a hash

Is it possible to have rails render html into a hash instead of to the client?
Something like this:
#obj = {
"foo" => Bar.find(1)
"html" => (render :partial => "yatzhee")
}
render :json => #obj.to_json
render_to_string takes all the same arguments as render but returns a string. You can then put that in a hash or do anything you want with that.
I never saw anything like that.
If you want to render json, you should really take a look at jbuilder. It's a joy to work with and it's the 'rails way' (~ it's merely built-in).
It allows you to render partials, for instance:
json.partial! "api/comments/comments", #message.comments

How to pass variables to render_to_string?

Trying to do the following
#message = render_to_string ( :sender => sender, :template => "template" )
But when accessing #sender in template it turns out to be nil:NilClass. Double checked if I pass the right variable and it's totally fine. Maybe there are other way to pass variables to render_to_string?
It might be the syntax you're using. Try using the :locals argument:
#m = render_to_string :template => "template", :locals => {:sender => sender}
Then you just need to access sender (without an #) as a local variable inside the template.
Here's Jason Kim's solution he wrote in a comment which worked for me:
ActionController::Base.new.render_to_string(
"user_mailer/welcome_email.html.erb", locals: { :#user => user}
)
Please mind the :#user => value bit.
In Rails 5 (atm in beta):
ApplicationController.render(
file: 'path',
assigns: { foo: 'bar' }
)
More here
Try this:
ac = ActionController::Base.new()
ac.render_to_string(:partial => 'path to your partial',:locals => {:varable => your variables})
In rails 4.0.2 this worked:
render_to_string(partial: 'path/to/partial', locals: { argument: 'value'}
I was trying to render a different format of partial in render_to_string. The thing which really worked for me was:
render_to_string(:partial => 'partial_file.html', :locals => {:variable => variable}, :format => :html)
where the name of the file was _partial_file.html.erb.

Resources