I want to render a response in JSON and then, check the JSON document generated by Rails from the browser. I can't do it because a TemplateNotFound exception is raised. It's weird to me because, as it's seen, JSON is sample text and shouldn't need a template.
def who_bought
#product = Product.find(params[:id])
#lastest_order = #product.orders.order(:updated).last
if stale?(#lastest_order)
respond_to do |format|
format.atom
format.xml { render :xml => #product.to_xml(:include => :orders)}
format.json { render json: #product }
end
end
end
Anyone knows what is missing?
To get a JSON response, request type must be JSON. Append .json to the url. For e.g. localhost:3000/posts.json would return JSON data.
Related
I am working on a ruby API's.This API fetching db value and converted into a JSON format.
This is the table data
Below code used to fetch data from db and converted into JSON format
def get_data
response= data.select(:xx, :xxx, :xxx, :xxx ).where(:id => xxx1,:xx1 => xx1)
if response.empty?
respond_to do |format|
msg = {:message => "No records found"}
format.json { render :json => msg }
end
else
respond_to do |format|
format.json { render json: response.to_json }
end
end
end
Now am getting the response like below
How can i remove the slash from the response?
Thanks in advance.
Note: I was tested this API's from POSTMAN
Executed following solutions but the result was same
use as_json instead of to_json
removed .to_json
I don't think you can use the variable response in a controller action.
It is already used by Rails: https://guides.rubyonrails.org/action_controller_overview.html#the-response-object
I have a simple remote form with one input and send button.
I created listener for ajax:success:
$ ->
$form = $('#post-form')
$form.on 'ajax:success', (e, data, status, xhr) ->
console.log e
console.log data
console.log status
console.log xhr
And my controller:
def create
#post = Post.new(post_params)
#post.user_id = 3
if #post.save
render partial: 'posts/view', locals: { post: #post }, status: :ok
else
render json: #post.errors, status: :unprocessable_entity
end
end
I see that request passes on backend and status 200 is returned:
Rendered posts/_view.html.erb (3.0ms) [cache miss]
Completed 200 OK in 480ms (Views: 466.6ms | ActiveRecord: 7.0ms)
But in devtools I see:
What am I doing wrong?
I'm not sure what you want to do with the data after you create the post, but in order to receive the data that was sent to an action via JSON, you have to return JSON from that action, as follows:
def create
#post = Post.new(post_params)
#post.user_id = 3
respond_to do |format|
if #post.save
format.html { render partial: 'posts/view', locals: { post: #post } }
format.json { render json: #post, status: :created }
else
format.html { render :new } # assuming you have a view file named "views/posts/new.html.erb"
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
This way you can handle the request if it's JSON and you can handle the request if it's just plain HTML.
Quick TL;DR:
Assuming your above code, this is the json response you're looking for:
e.detail[0]
This vexed me a bit as well. Interrogating the one object that came back lead me to my answer- the result body is available in the event that comes back. My Rails app is not using jQuery, so the resultant event object is an ajax:success result.
The result has a field called detail which (in my case) contained three items: the data from the response body of the called request (which I believe is what you're looking for), the String "OK" and the XMLHttpRequest that made the call.
So, in your above form.on callback, if you interrogate e.details[0], I think you'll find the json data (also, the other params in the callback are unnecessary).
My assumption is that somewhere along the line, the callback logic for remote calls was simplified to a single parameter containing all the code. Looks like this happened when the removed the dependency to jQuery for UJS: https://guides.rubyonrails.org/working_with_javascript_in_rails.html#rails-ujs-event-handlers.
The technique I have used in the past is the replace a section of the DOM as part of the AJAX request, i.e.
def create
#post = Post.new(post_params)
#post.user_id = 3)
respond_to do |format|
format.js
end
end
And in /views/posts/create.js.erb
$("#new_item").html("<%= escape_javascript(render partial: 'posts/view', locals: { post: #post } ) %>");
Take a look at this link.
Let's assume I have a controller action that whenever you try to access it via a js format, I want to render nothing.
def no_js_please
# there isn't a no_js_please partial or view
respond_to do |format|
format.html { # render a template }
format.json { render json: {valid: true} }
format.js { render nothing: true, status: :not_found }
end
end
When you access the endpoint via html or JSON, it works just fine. When you try to access it via JS it doesn't work. However, it does actually execute the block, because if I add a binding.pry within the js block, it gets picked up.
However, this does work:
def no_js_please
if request.format.js?
render nothing: true, status: :not_found
end
end
So what's the difference between the two?
EDIT
As a human mentioned below, what's the actual error? So, in this particular case, it raises a ActionController::InvalidCrossOriginRequest.
Use "head" instead of "render nothing: true". The latter is actually deprecated in Rails 5+ anyway.
def no_js_please
respond_to do |format|
format.html { # render a template }
format.json { render json: {valid: true} }
format.js { head :not_found }
end
end
This will get you the result you're looking for and it will be one less line to change when you upgrade.
Rails scaffold generated the following:
respond_to do |format|
if #student.save
format.html { redirect_to #student, notice => 'Student was successfully created.' }
format.json { render :show, status: :created, location: #student }
else
format.html { render :new }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
After reading this I understand how the respond_to is working (sort of), but I don't get what format is doing. Shouldn't it be either format.html or format.json and not both? What are these two lines actually doing?
format.html { render :new }
format.json { render json: #student.errors, status: :unprocessable_entity }
Is there an implied if in there? Is it something like
if (format == html) {}
if (format == json) {}
Side note: Why does update require the respond_to block while show will handle /students/1.json or /students/1 without any logic at all?
format is a local variable that respond_to yields. When you do format.html {} you are actually registering a callback block for a format.
Rails goes through the registered formats and tries to find a compatible format to the MIME type in the request. If there is no handler it will raise an error.
This could be explained as something like using syntactic sugar on top of a case statement (the Ruby equivalent of a switch statement). But the analogy is not completely accurate since Rails does a bit of work in matching the request type.
Also the code inside your block is not executed when the format.html block is registered (as it would be if it was just a conditional statement) but rather when respond_to finishes or not at all if you are using for example E-Tag caching.
Why does update require the respond_to block while show will handle
/students/1.json or /students/1 without any logic at all?
Rails handles many actions by using a convention over configuration approach and guessing the intent of the action.
def PostsController < ApplicationController
def index
# rails auto-magically fills in the controller with something
# like this
#posts = Post.all
respond_to do |format|
format.html { render :index }
format.json { render json: #posts }
end
end
def show
# convention over configuration is awesome!
#post = Post.find(params[:id])
respond_to do |format|
format.html { render :show }
format.json { render json: #post }
end
end
def new
#post = Post.new
render :new
end
def edit
#post = Post.find(params[:id])
render :edit
end
end
Rails assumes that there is a resource with the same name as the controller and auto-magically fills in the controller action. It also assumes there is a view in app/views/posts/(:action).html.[erb|haml|slim|jbuilder]. This is known as implicit rendering.
The comments show roughly what action rails attempts.
It does not fill in actions which operate on data (create, update, destroy) since the actual implementation can vary greatly and it's hard to make useful guesses.
Well, it depends on the format of the request. If a request demands HTML from the server, format.html block will be executed, and in the same way, if a request demands JSON format, format.json will be executed.
Rails will automatically(read: magically) handle the if (format == html) part for you. All you have to do is fill in the blanks. Same way, you can write a block for XML starting with format.xml.
And for the side note, I think you have said it otherwise. update method doesn't require respond_to block, while show requires. And the reason is very simple: update method is there to update the Model, and then, redirect you to somewhere, while show will always return you something. In your case, /students/1 will return you the first student created in the database, and the response will be HTML, while /students/1.json will return you the same result, but response will be JSON this time.
Well you could very well replace 'format' with 'foo' or 'banana' or whatever you want. It is just the variable name in this case because the variable that is sent to your block by respond_to is passing along the format as requested by the incoming http request's Accept header.
Sometimes you'll see 422 "Unacceptable" errors in your logs because you are receiving a request with an Accept header that does not request a mime type your app knows about.
As it is, your callers should be using a browser or be a JSON consumer sending the proper headers to receive responses from the boilerplate.
Am working in rails. If I send a request like http://www.example.com/titles/search?search_text=something
as a respond I need a Json .How to implement this in Rails?
If you want a response in JSON format then you need to pass your request as url.json format.
In your controller, inside that action check your request format and return the result according to the requested format. You can read more about this here and having example source code as wel. Check it out here Rendering JSON and other formats.
respond_to do |format|
format.html {}
format.json {
render :json => #your_obj.to_json, :callback => params[:callback], :content_type => "text/html" }
format.xml { render :xml => response }
end
In your titles contoller in particular action, having a search_text as get param use
render json: #object
detailed: http://guides.rubyonrails.org/layouts_and_rendering.html#using-render (2.2.8)