I have a jbuilder file to make a special json output for an object.
My routes has the resource added in as a collection block and going to the URL with .json at the end works fine. How do I force the json format in that method only? I know you can set respond_to :json in the controller overall but not for a single method. How do i do that?
this , :defaults => {:format => 'json'} after the get 'xxx' in the collection do block does it
Related
When making POST/PATCH requests to my rails webapp, I send the data as json. For example this json data {"name" => "Hallo", "status" => "admin"} to an controller named UsersController. The setting for wrap_parameters in the wrap_parameters.rb file are the default values:
ActiveSupport.on_load(:action_controller) do
wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
end
So every json data gets wrapped like this "user" => {"name"=> "Hallo", "status" => "admin"}. This is how it should be. However when I call a custom method called status which is located in ApplicationController to check the server status, all following requests json data won't get wrapped in their controllers/models name hash, but in a hash like this "application" => {"name"=> "Hallo", "status" => "admin"}.
This is for all following requests until I restart the server. Moreover if I want to keep the "right" behavior I can't call the status method in ApplicationController again which would lead to the "application" => {...}wrapping.
What I found out is when I set Content-Type = text/html (It was Content-Type = application/json before) for my request to the status method the following request are not polluted, meaning I get the right wrapping behavior.
However this is very disturbing, as someone just needs to call the status method, when Content-Type = application/json is set for the request and all the following POST/PATCH requests won't work anylonger.
I don't know if this matters, but I set the following in routes.rb:
namespace :api, defaults: {format: :json} do
namespace :v1 do
...
match "/status", to: "application#status", via: "get"
...
end
end
There's one tricky thing in the wrap_parameters method. You can specify the format as you did but ParamsWrapper is getting the format from request.content_mime_typeinstead of request.format so if you're trying to do POST/PUTrequest, ParamsWrapper format is multipart_form and not json.
So instead of:
wrap_parameters format: [:json]
you have to do:
wrap_parameters format: [:json, :multipart_form]
Source: https://github.com/rails/rails/blob/dda31d59a03adb7e5aa372e72bb66a3886632f2f/actionpack/lib/action_controller/metal/params_wrapper.rb#L281
I'm working on a vanilla Rails 4.2 app for a demo of building a JSON API with Rails.
bundle exec rails g scaffold widget name
Out of the box, Rails provides an easy way to fetch a resource as JSON by simply adding .json to the end of the URL.
/widgets.json
# or...
/widgets/123.json
However, I was wondering what is the most simple way to allow Rails to respond as JSON by using other means than simply appending .json. Do I need to send an Accept header in the request? Or do I have to explicitly respond_to :json in order to add this support? I also need to continue to support HTML, but wanted a clean URL. What do I need to do?
For defining all the routes to json use the following code.
resources :you_resouce, :defaults => { :format => 'json' }
For specific route use the following code.
scope :format => true, :constraints => { :format => 'json' } do
get '/endpoint' => "controller#action_method"
end
I have a simple controller with a show and a index method. routes.rb has a resources :foo entry and when I go to localhost:3000/foo I get an missing template error even though I have an index.json.jbuilder file in the correct folder which is easily enough shown when I go to /foo.json
Shouldn't rails see that there isn't a html template for this particular view and use the json template automatically?
I am using rails 4.2.
Going to localhost:300/foo will by default use the :html format. Since you don't have the corresponding html view, you'll get the missing template error. If you want the route to default to :json you can specify it when defining the route
resources :foo, defaults: {format: :json}
From official documentation:
The next part of the message contains a hash. The :locale key in this hash simply indicates what spoken language template should be retrieved. By default, this is the English - or "en" - template. The next key, :formats specifies the format of template to be served in response. The default format is :html, and so Rails is looking for an HTML template. The final key, :handlers, is telling us what template handlers could be used to render our template. :erb is most commonly used for HTML templates, :builder is used for XML templates, and :coffee uses CoffeeScript to build JavaScript templates.
This is why Rails can't find your .json.jbuilder view. So, in your case you can pass correct Accept HTTP header or override request format:
before_filter :default_request_format
def default_request_format
request.format = :json
end
or specify it in routes as described #Bart Jedrocha above.
I am new to Ruby On Rails and need some help implementing REST protocol.
Whenever you do a POST on REST you get a URL back e.g. http://my-site.com/id/1
I need a customized response in URL format which I have given in example above.
Lets say I am doing a post on parameter <main-id>123</main-id>
The customized response I am looking for is http://my-site.com/123/id/1
What I want to implement is, whatever parameter ID I passed during a post I want that as a part of the response URL output.
Thanks for any help in advance.
You can specify any URL in your controller, e.g.:
def create
... # create record here
redirect_to "/#{params[:main_id]}/id/#{#record.id}"
end
Of course, you'll probably want to use the url helper based on your defined route:
def create
... # create record here
redirect_to my_oddball_path(#record, :main_id => 123)
end
Provided you are using Rails 3, you could just add this route with the proper controller/action
match ':main_id/id/:id', :controller => 'foo', :action => "bar", :via => :post, :as => main_id
Then you can just with the helper main_id_path(main_id, #record)
I am generating a url in my controller accessed from the relative path "/hangouts/test", for a url on an external site (facebook). I want to use url_for and pass in params using hashes so it can escape them. The URL I want is this:
http://www.facebook.com/connect/prompt_permissions.php?api_key=6aca22e72866c7eaaedfb15be69c4b93&...
Using this, however:
url_for(:host => "www.facebook.com/connect/prompt_permissions.php?", :api_key => Facebooker.api_key, :next => test_hangouts_url, :cancel => root_url, :ext_perm => "publish_stream")
I instead get my current path of /hangouts/test thrown in there:
http://www.facebook.com/connect/prompt_permissions.php/hangouts/test?api_key=6aca22e72866c7eaaedfb15be69c4b93&...
As you can see, I don't want "/hangouts/test" to be in there - played a bit with the options in the API docs but stumped, anybody know how to use url_for without it inserting the current path? Thanks!
You shouldn't be using the hash form of url_for to generate links outside of your application.
Instead you should just be using the string version form:
url_for "http://www.facebook.com/connect/prompt_permissions.php?api_key=6aca22e72866c7eaaedfb15be69c4b93&next=#{test_hangouts_url}&cancel=#{root_url}&ext_perm=publish_stream"
url_for will use the current action controller/action/id unless the hash given to url_for contains one of those arguments. url_for will then generate a url from a route that matches the arguments given in the hash. The arguments to url_for used in the question generates a valid url, because it can match a route using the current controller/action. You will not be able to generate the url you want with the hash form of url for without matching a route. Providing a controller in the hash you give url_for should match the default routes that rails generates for you when you create an application, but that's not very DRY.
The better solution is to use a named route:
map.prompt_fb_permissions "/connect/prompt_permissions.php",
:host => "www.facebook.com", :controller => nil, :action => nil
then you can use the following in place of url_for whenever you want to generate this this url.
prompt_fb_permissions(:api_key => Facebooker.api_key, :next => test_hangouts_url,
:cancel => root_url, :ext_perm => "publish_stream")
You left out the controller parameter, which is why it's automatically adding your controller path ("/hangouts/test"), to your base host.
Try this:
url_for(:host => "www.facebook.com", :controller=> "/connect/prompt_permissions.php", :api_key => Facebooker.api_key, :next => test_hangouts_url, :cancel => root_url, :ext_perm => "publish_stream")