Combing two methods in rails [duplicate] - ruby-on-rails

In my rails app I have a ajax request to the server, to store some data. This used to work without any problem, but now I get an error:
ActionController::UnknownFormat (ActionController::UnknownFormat):
app/controllers/reservations_controller.rb:45:in `create'
As following is the controller and my javascript file where I declare the datatype do be JSON
class ReservationController < ApplicationController
respond_to :html, :json
def create
...
respond_to do |format|
if #reservation.save
format.html do
redirect_to '/'
end
format.json { render json: #reservation.to_json }
else
render 'new'
end
end # respond_to
end # create
end # ReservationController
function.js
$.ajax({
url: url_link,
dataType: 'json',
type: 'POST',
data: dataToSend
})
The complete error log is:
Completed 406 Not Acceptable in 45ms
ActionController::UnknownFormat (ActionController::UnknownFormat):
app/controllers/bookings_controller.rb:45:in `create'
Rendered /Users/tiagovieira/.rvm/gems/ruby-2.0.0-p451/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_source.erb (0.5ms)
Rendered /Users/tiagovieira/.rvm/gems/ruby-2.0.0-p451/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_trace.erb (0.8ms)
Rendered /Users/tiagovieira/.rvm/gems/ruby-2.0.0-p451/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (0.8ms)
Rendered /Users/tiagovieira/.rvm/gems/ruby-2.0.0-p451/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (9.6ms)

Update the create action as below:
def create
...
respond_to do |format|
if #reservation.save
format.html do
redirect_to '/'
end
format.json { render json: #reservation.to_json }
else
format.html { render 'new'} ## Specify the format in which you are rendering "new" page
format.json { render json: #reservation.errors } ## You might want to specify a json format as well
end
end
end
You are using respond_to method but anot specifying the format in which a new page is rendered. Hence, the error ActionController::UnknownFormat .

You can also modify your config/routes.rb file like:
get 'ajax/:action', to: 'ajax#:action', :defaults => { :format => 'json' }
Which will default the format to json.
It is working fine for me in Rails 4.
Or if you want to go even further and you are using namespaces, you can cut down the duplicates:
namespace :api, defaults: {format: 'json'} do
#your controller routes here ...
end
with the above everything under /api will be formatted as json by default.

There is another scenario where this issue reproduces (as in my case). When THE CLIENT REQUEST doesn't contain the right extension on the url, the controller can't identify the desired result format.
For example: the controller is set to respond_to :json (as a single option, without a HTML response)- while the client call is set to /reservations instead of /reservations.json.
Bottom line, change the client call to /reservations.json.

This problem happened with me and sovled by just add
respond_to :html, :json
to ApplicationController file
You can Check Devise issues on Github: https://github.com/plataformatec/devise/issues/2667

Well I fond this post because I got a similar error.
So I added the top line like in your controller
respond_to :html, :json
then I got a different error(see below)
The controller-level respond_to' feature has been extracted to theresponders` gem. Add it to your Gemfile to continue using this feature: gem 'responders', '~> 2.0' Consult the Rails upgrade guide for details.
But that had nothing to do with it.

I got this error when trying to render an XML response - I had to change my template name from index.html.erb to index.xml.erb and then it worked.

mine was fixed because i didnt have / / in the scope,
i had this (getting error for json):
Rails.application.routes.draw do
scope '(:base_url)', base_url: #{ENV.fetch('BASE_URL').to_s} do
...
end
end
instead of this (fixed):
Rails.application.routes.draw do
scope '(:base_url)', base_url: /#{ENV.fetch('BASE_URL').to_s}/ do
...
end
end

Related

Rails routes: json endpoint naming convention

I have an endpoint that renders json:
def controller_method
render json: json_response
end
However, I am curious about the naming convention of the route. The following naming leads to ActionController::UnknownFormat Controller#controller_method is missing a template for this request format and variant.:
get '/controller/controller_method.json', to: 'controller#controller_method'
However, I successfully get the json when the route is named:
get '/controller/controller_method_data', to: 'controller#controller_method'
Am I not allowed to put .json in the url routes? Any way that I can allow .json be the name of the route?
There is a much easier way to respond to different formats - just use ActionController::MimeResponds
get '/controller/controller_method', to: 'controller#controller_method'
class Controller < ApplicationController
def controller_method
respond_to do |format|
format.json { render json: { hello: 'world' } }
format.html # renders the view implicitly
format.txt { render plain: 'Hello world'}
end
end
end

can I use rabl without using .json in the url?

I have rabl up and running.
I have this in routes:
get 'biblios/collection/:biblio_urn' => 'biblios#biblio_rabl', as: 'collection_biblio'
in the controller:
def biblio_rabl
biblio = Biblio.where(biblio_urn: params[:biblio_urn]).take
end
This url points to the correct result :
http://localhost:3000/dts/biblios/collection/urn:cts:froLit:ed_desmarez:1900
I would like that url to always respond using rabl and showing the the template dts/biblios/biblio_rabl.json.rabl
I mean without adding .json at the end of the url.
I have tried this in the routes.rb, but it doesn't redirect :
get 'biblios/collection/:biblio_urn' => 'biblios#biblio_rabl', as: 'collection_biblio', to: redirect('biblios/collection/%{biblio_urn}.json')
Is that possible at all?
You can force the response to be json by changing the request format in the controller:
request.format = :json
Then make sure you have a respond_to block like this because it's always better to be explicit about your responses:
def biblio_rabl
respond_to do |format|
format.json { json: Biblio.where(biblio_urn: params[:biblio_urn]).take }
end
end

Internal server error 500 on missing image file (Rails 3.2.12)

If we request a bogus image file, Rails generates an internal 500 server error instead of a 404. See the log below.
Here is the line in routes.rb that catches 404s:
# Catches all 404 errors and redirects
match '*url' => 'default#error_404'
Other unknown URLs are handled correctly with 404s. What is different for image files and URLs with file extensions?
Started GET "/images/doesnotexistyo.png" for 71.198.44.101 at 2013-03-08 07:59:24 +0300
Processing by DefaultController#error_404 as PNG
Parameters: {"url"=>"images/doesnotexistyo"}
Completed 500 Internal Server Error in 1ms
ActionView::MissingTemplate (Missing template default/error_404, application/error_404 with {:locale=>[:en], :formats=>[:png], :handlers=>[:erb, :builder]}. Searched in:
* "/home/prod/Prod/app/views"
The problem is that the error_404 method inside the Default controller can't handle requests in png format. When you ask for say, a JSON response, you could build an URL similar to:
/controller/action.json
And inside the action you would have something like
def action
respond_to do |format|
format.html # Renders the default view
format.json { render :json => #model }
format.xml { render :xml => #model }
end
end
As you can see, it's specified how to handle a JSON and an XML request, but since there's no format.png, the action can't handle the .png format. Add this:
format.png # Handle the request here...
Hope it helps :)
Edit
Add this to redirect to your 404 handler:
def error_404
respond_to do |format|
format.html
format.png { redirect_to :controller => 'default', :action => 'error_404' }
end
end
Cheers :)
Edit2
Use this code to catch all kinds of requests:
def error_404
respond_to do |format|
format.html { render :not_found_view }
format.all { redirect_to controller: 'default', action: 'error_404' }
end
end
Replace :not_found_view with your 404 page. This will render the 404 page for html requests, and redirect to self (with html format) for any other kind of request.
Hope it helps :)
What is DefaultController? That controller is dealing with the 404, instead of Rails default response:
ActionController::RoutingError (No route matches [GET] "/images/doesnotexistyo.png"):
So find out this controller, error_404 is being executed and no template default/error_404 was found, hence the 500 error.
You probably have a code similar to this somewhere in your code:
rescue_from ActiveRecord::RecordNotFound, :with => :error_404
Maybe not for you, but since I do some final checks for pages dynamically in my controllers, I just follow all my 404'ing with one to handle non-html files:
format.all { render :status => 404, :nothing => true }

Rails 3 route with json format not working

I have a route that I need to call like so:
/images/get_subcollections.json?id=1234
I have this in my routes file:
resources :images do
collection do
get 'get_subcollections'
end
end
I have this in my controller:
def get_subcollections
collection = Collection.find(params[:id])
respond_to do |format|
format.json { render :layout => false, :json => collection.to_json(:methods=>:get_subcollections) }
end
end
The app just sits there when I call the URL. The request doesn't get logged or anything. Any ideas? Thanks!
Have you inspected the response using firebug or chrome's dev tools? Is it just that layout: false is stopping you seeing anything?

Preventing direct URL access to Rails Controller Methods

I have a particular Rails controller method that returns some JSON when I do an javascript ajax request in the front-end.
However, I want to prevent users from directly typing in the url, which displays the JSON that the method returns. I also want to still be able to perform my ajax requests. How can I go about doing this simply? Thanks!!
Just a thought... You could do something custom in your respond_to block for html requests.
respond_to do |format|
format.html { ... } # give them a 404 response?
format.js { render :json => #obj }
end
Or maybe your html.erb template with that name could just show some kind of access denied message. Then you'd just have this:
respond_to do |format|
format.html
format.js { render :json => #obj }
end
You could wrap your action with
if request.xhr?
...
end
The respond_to filter in rails3 controllers is pretty sweet.
YourJsonController < ApplicationController
respond_to :json
def index
#non-json requests will receive a 406 error
end
end
In your routes.rb, you can add :via => :post so your URL accepts only POST requests. See "HTTP Verb Constraints" at http://guides.rubyonrails.org/routing.html

Resources