I'm currently trying to return multiple JSON objects in one of my controllers as such.
#chromosomes = #organism.chromosomes.to_json
#file_data = current_user.files.to_json
respond_to do |format|
format.html
end
However, on the front end when I do:
<%= #chromosomes %>
or
<%= #file_data %>
I don't get a JSON object, instead I get the data as a string with things such as "e, etc. I've tried parsing the string such as
console.log($.parseJSON("<%= #chromosomes %>"));
but it still isn't working. Is this is because the request being sent back is html?
Thanks!
Your code should look something like this,
respond_to do |format|
format.html index.html.erb
format.xml { render :xml => #organism.chromosomes) }
format.json { render :json => #organism.chromosomes) }
end
You just need
render :json => #organism.chromosomes
By looked at you edit, I think what you want is below:
console.log($.parseJSON("<%= raw #chromosomes %>"));
The problem ended up lying in the fact that Rails encoded the json data as a string, which is the default. To fix the issue I used
<%= #chromosomes.html_safe %>
on the front end. Further info about this can be found here:
Weird JSON Javascript problem in Rails
This should work, for Rails 2,
console.log($.parseJSON(<%= #chromosomes.dump %>));
for Rails 3,
console.log($.parseJSON(<%= #chromosomes.dump.html_safe %>));
String#dump escapes the characters and makes parseJSON() work. Notice that no quotation marks needed.
Related
I have a old rails 2.x project that I have converted mostly over to rails 5.
One issue is some of my actions used RJS, so it looked like:
if request.xhr?
render :action => 'new_user' and return
end
The new_user.js.rjs looks something like:
page.call "User.create", render(:partial => 'new_user'), {:userId => #user.id}
Looking at the response in chrome I can see it is just returning:
User.create('<tr><td>....</td></tr>', {"userId" : 123});
I only have to support the page.call type RJS call, what would be a easy "hack" to get this to work in rails 5?
I don't want to modify all of my javascript code, I just need to basically have a javascript block that I pass the JS code to in my view pages right?
Try to render a response as a string:
if request.xhr?
render render_to_string partial: 'new_user',
locals: { userId: #user.id },
layout: false
end
Or try to use format handler instead:
respond_to do |format|
format.rjs do
render render_to_string partial: 'new_user',
locals: { userId: #user.id },
layout: false
end
end
I ended up returning a JSON response to my view pages like this:
some_partial_html = render_to_string(:partial => 'something')
response = {
"html": some_partial_html,
"a" : 1
}.to_json
render json: response
And then in my view I used the json response values as arguements to the javascript object that performs the functionality I needed.
I'm aware of the other questions pertaining to this subject, but none seem to help. I want the paperclip image url passed to json so I can render it in a reactjs component. I obviously cannot use Rails' image_tag helper.
I've defined this method in my items model
def image_url
image.url(:thumb)
end
And this in my controller
def index
#items = Item.all
render :json => #items.to_json(:methods => [:image_url])
end
But literally all that does is replace the rendered page with json. How should I go about this? It doesn't make sense to create a migration and model validation specifically for the image url.
Just needed to format the html.
respond_to do |format|
format.html
format.json { render :json => #items.to_json(:methods => [:image_url]) }
end
Still doesn't solve the part where I'm trying to use that method in a reactjs component, but that's another issue.
Using rails and .js.erb to make an AJAX request (and append values to a div), how do you prevent rendering a new layout? In other words, stay on the same page without going anywhere and just append the fresh data from the server in a div. No reloading the same page, no redirecting.
At the moment my controller looks like this
def update_shipping
#order = Order.find(params[:id])
#order.shipping_option_id = params[:shipping_options]
#order.save!
respond_to do |format|
format.js
format.html
end
end
and my form like zisss:
<%= form_tag update_shipping_order_path(#order), method: :put, remote: true do %>
<%= select_tag 'shipping_options', #options_for_select, onchange: 'this.form.submit()' %>
<% end %>
and my routes look like a so:
resources :orders do
member do
put :update_shipping
end
end
But I get a 'Template is Missing' error
Please help!!
You need to add a update_shipping.js.erb file under app/views/your_controller/ directory. Note the name of the javascript file should be same as the action. Since you have a remote:true in your form so rails will try to render a javascript template in your case update_shipping.js.erb.
Now in your update_shipping.js.erb file write some basic javascript to update the page elements like
#update_shipping.js.erb
$('.some-div').html(<%=j #model.some_value' %>)
Try this:-
respond_to do |format|
format.js { render :nothing => true }
format.html
end
If you don't want to render a layout, you can use !request.xhr? like so:
respond_to do |format|
format.html { layout: !request.xhr? }
format.js
end
If you're looking to get your ajax-powered JS to fire, you just need to call your .js.erb file the same as your view:
#app/views/controller/update_shipping.js.erb
alert("This JS is returned & fired after the Ajax request");
You'll be best doing this in your routes.rb too:
resources :orders do
put :update_shipping
end
A little late, I came across this searching for the same issue. It must of slipped out of my mind at some point while working with action cable, but what is needed is a http response code of no_content. Http response codes tell the browser how to act when a request is returned. Here is a link to a list of them, and their symbols in rails. More on 204 no content
Here is how it would look:
def update_shipping
#order = Order.find(params[:id])
#order.shipping_option_id = params[:shipping_options]
#order.save!
head :no_content #or head 204
end
edit: what solved the solution for me was a link provided by William Denniss in this stack overflow question
I know that if I have a url like
mysite/posts/1
The default type returned to me is html. I can get an xml version of the resource by just doing
mysite/posts/1.xml
But how do I get a json version? Is the following supposed to work?
mysite/posts/1.json
Reason I ask is because it doesn't seem to be working. So I figured I should find out if it's "supposed" to work this way before investigating further.
You're doing it right, but if the Controller isn't setup to respond to json requests you won't get anything. You'll have a respond_to block like this:
respond_to do |format|
format.html
format.xml { render :xml => #model_var.to_xml }
format.json { render :json => #model_var.to_json } #without this line, .json requests will go unanswered by the web server.
end
Good afternoon,
I'm trying to render as XML the complete ActiveRecord error list, problem is when you do something like:
respond_to do |format|
format.xml { render :xml => #object }
end
It does not render nested attributes if you don't say so, so either: you should create a template or calling explicity to_xml method and using ":include". This last option seems to work fine with nested attributes on model associations. But what if we got errors? This code does not work:
respond_to do |format|
format.xml { render :xml => #client.to_xml(:include => :errors }
end
I know I could do #client.errors and even hide .to_xml, but now i want to do something like:
respond_to do |format|
format.xml { render :xml => #client.to_xml(:include => {
:errors,
:client_contact => {:include => :errors } } )}
end
And supposedly I could obtain only in 1 xml, the errors from the client, and the errors from the client.client_contact! Let me know if i'm doing something wrong, or this :include is not supposed to work with errors
Regards
Have a look at the documentation for XML builder in the API docs. You can generate XML based on any number of conditions and output it however you like.
There's also a Railscasts episode showing you how to do a similar thing for RSS feeds.