Rails Test post Request with firefox plugin results in bad request - ruby-on-rails

I m trying to test the create method of my rails App , I cant figure out what is wrong and why constantly having "bad request".
The routing goes line this:
namespace :api do
namespace :v1 do
resources :routes
resources :line_items
end
end
My controller is like this:
def create
#route = Route.new(permitted_params)
respond_to do |format|
if #route.save
format.json { render json: #route, status: :created }
else
format.json { render json: #route.errors, status: :unprocessable_entity }
end
end
end
My permitted params are these:
def permitted_params
params.require(:route).permit(:comment)
end
I use the firefox plugin OpenHttpRequester and this is what I get when I click to POST button, when I insert submit my json = route:{comment:"bla"}
Any ideas what of what the request should be ?
I have changed the json part to {"route":{"comment":"bla"} and get a nice 422 response.. still no luck

I was missing the following line in the controller:
skip_before_filter :verify_authenticity_token

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

add XML support to JSON handling functions in ROR

In my heroku RoR app,I have a controller in which I support JSON requests. There I have the following functions:
def mssg_as_json
#message = Message.new
#message.text = params.require(:messages)
#message.save
string = "http://link.com/"
#message.url = string + #message.id.to_s
#message.save
render json: { url: #message[:url] }
end
def return_mssg_as_json
if #message = Message.find_by(id: params[:id])
render json: { message: #message[:text] }
else
render json: {errors: :not_found}, status: :not_found
end
end
I want to support XML requests too. My idea is to somehow convert the XML to JSON but I have no idea how. How can I modify the code to support both XML and JSON?
P.S.
My routes are:
get "messages/api" => "messages#return_mssg_as_json"
post "messages/api" => "messages#mssg_as_json"
The requests are send to main_url/messages/api
So, you should take advantage of the standard routes and actions. In routes.rb, you might do something like:
Rails.application.routes.draw do
resources :messages
namespace :api, defaults: {format: 'json'} do
namespace :v1 do
resources :messages
end
end
end
Note that your controller is now nested inside api/v1. That allows you to identify the path as an api and to maintain versions over time. That solid's practice. Also note that you have a standard messages resource for your web app.
Then, your controller would look like:
class Api::V1::MessagesController < Api::V1::BaseController
def create
#message = Message.new(message_params)
respond_to do |format|
if #message.save
#message.update(url: "http://link.com/#{#message.id}")
format.json { render json: create_hsh, status: :ok }
format.xml { render xml: create_hsh, staus: :ok }
else
format.json { render json: #message.errors, status: :unprocessable_entity }
format.xml { render xml: #message.errors, status: :unprocessable_entity }
end
end
end
def show
respond_to do |format|
if #message = Message.find_by(id: params[:id])
format.json { render json: show_hsh, status: :ok }
format.xml { render xml: show_hsh, status: :ok }
else
format.json { render json: {errors: :not_found}, status: :not_found }
format.xml { render xml: {errors: :not_found}, status: :not_found }
end
end
end
private
def create_hsh
#message.attributes.with_indifferent_access.slice(:url)
end
def show_hsh
attr = #message.attributes.with_indifferent_access
attr.slice(:foo, :bar).merge!(message: attr[:text])
end
def message_params
params.require(:message).permit(:text)
end
end
Note that this controller inherits from Api::V1::BaseController. That would be a controller that you set up to do api-relevant client authentication (key/token checking, etc.). Something, perhaps, like:
class Api::V1::BaseController < ActionController::API
before_action :authorize
def authorize
# do your checks in a way that results in a variable #authorized?
render(json: {errors: :unauthorized}, status: :unauthorized) unless #authorized?
end
end
So, now you're using a single controller action to respond to all format types (that you elect to offer). Then, you clients would post something like:
http://your.api.com/messages.json
To get a json response. Or:
http://your.api.com/messages.xml
To get an xml response. You might notice the bit that says: namespace :api, defaults: {format: 'json'} do. This means that your client could call:
http://your.api.com/messages
and it will default to the json format.
Now you don't have a bunch of random endpoints (like mssg_as_json), just the regular RESTful ones that your clients will expect. Your API clients will love you for that.
You'll note that show_hsh is the accepted code from your earlier question.

In Rails, why am I getting a "204 - No Content" response for my update/PATCH/PUT, using Active Model Serializers?

This code is for a UserList (a user can create a User To-Do List). This particular resource does not hold the list items, but just the title of the list, and the type of list.
class Api::V1::UserListsController < ApplicationController
respond_to :json
skip_before_filter :verify_authenticity_token
def index
if authenticate_user
user_lists = #current_user.user_lists
if user_lists
respond_with user_lists, each_serializer: Api::V1::UserListSerializer
else
render json: { error: "Could not find user's lists."}, status: :not_found
end
else
render json: { error: "User is not signed in." }, status: :unauthorized
end
end
def show
if authenticate_user
user_lists = #current_user.user_lists
user_list = user_lists.find_by_id(params[:id])
if user_list
respond_with user_list, serializer: Api::V1::UserListSerializer
else
render json: { error: "Could not find user's list."}, status: :not_found
end
else
render json: { error: "User is not signed in." }, status: :unauthorized
end
end
def create
if authenticate_user
user_list = #current_user.user_lists.new(user_list_params)
if (user_list.save!)
respond_with :api, :v1, #current_user, user_list, serializer: Api::V1::UserListSerializer
else
render json: { error: "Could not create new User List."}, status: :unprocessable_entity
end
else
render json: { error: "User is not signed in." }, status: :unauthorized
end
end
def update
if authenticate_user
user_list = #current_user.user_lists.find_by_id(params[:id])
if (user_list.update_attributes(user_list_update_params))
respond_with :api, :v1, #current_user, user_list, serializer: Api::V1::UserListSerializer
#respond_with user_list, serializer: Api::V1::UserListSerializer
else
render json: { error: "Could not update User List." }, status: :unprocessable_entity
end
end
end
private
def user_list_params
params.require(:user_list).permit(:user_id, :type_id, :title)
end
def user_list_update_params
params.require(:user_list).permit(:type_id, :title)
end
end
Now the update works when I PUT/PATCH... but I get a
Completed 204 No Content in 24ms (ActiveRecord: 4.3ms)
It's been about 4+ months since I've done any rails, and back then I was only just beginning to learn it.
1) Does anyone know why I'm not getting anything back? I know it's something to do with my respond_with line of code in update, but I'm not sure exactly what.
2) Can someone clarify to me the difference between the SHOW respond_with and the CREATE respond_with. I recall having an issue grasping this back then, and obviously now.
SHOW
respond_with user_list, serializer: Api::V1::UserListSerializer
CREATE
respond_with :api, :v1, #current_user, user_list, serializer: Api::V1::UserListSerializer
a) Why does create require :api and :v1 first, but show does not?
b) Why does create require the #current_user, but show does not?
Appendix: Here is my Serializer for reference
class Api::V1::UserListSerializer < ActiveModel::Serializer
attributes :id, :user_id, :type_id, :title
has_many :items, embed: :ids
end
I know this is 2 years too late, but after some digging, I found the empty response with the 204 is intentional (as mentioned above). If you use respond_with this will always be the case. A workaround would be to use render instead (example below):
class Api::V1::ItemsController < ApplicationController
respond_to :json
...
def update
#item = Item.find(params[:id]
if #item
#item.update_attribute(item_params)
render json: #item
end
end
...
end
You're not supposed to get anything back other than the 204. Any intelligent client does not need to receive back the data it just sent you -- it needs only confirmation that the data was persisted.
Do not mistakenly pass your class Api::V1::UserListSerializer as a key/value pair (Hash form). You will get an error including the text class or module needed. It should look like this:
serialize :some_array, Api::V1::UserListSerializer
Or, perhaps clearer would be:
serialize(:some_array, Api::V1::UserListSerializer)
You miss one param and you are rendering an object class with no content : 204 - No Content
That may seem obvious, but it is common to be in the habit of passing things as a key/value pair.
One improve:
before_action :authenticate_user, only: [:create, :show, :update, ...]
https://apidock.com/rails/ActiveRecord/Base/serialize/class
def update
#item = Item.find(params[:id])
respond_with(:api, :v1, #item) do |format|
if #item.update(item_params)
format.json { render json: #item}
else
format.json { render json: {error: #item.errors.full_messages}}
end
end
end

Rails 4 - Nested resources - REST API render json error

I have these routes:
resources :championships do
resources :rounds do
resources :games
end
end
When I try to insert a game by POST I got this error:
NoMethodError in GamesController#create
undefined method 'games' for nil:NilClass
But the data is inserted correctly!
Part of GamesController:
before_filter :load_round
def create
#game = #round.new(model_params)
if #game.save
render json: #game, status: :created, location: #round
else
render json: #game.errors, status: :unprocessable_entity
end
end
private
def model_params
params.require(:game).permit(:team_1_id, :team_2_id)
end
def load_round
#round = Round.find(params[:round_id])
end
PS: I am using the same logic to include Rounds inside a Championship whith no problem
As seen in comment, the issue here comes from the location: #round.
As stated in the Rails documentation, the location param sets the HTTP Location header.
It takes an URL as value. It should work if you change this to use the rails url helpers location: round_url(#round), if your round route is not namespaced or nested.

Rails 3.2 redirection skips Create action

I have a Rails 3 blog-style application, where I've got an admin namespace for backend purposes and a controllers/admin subfolder containing the respective posts_controller.rb.
So the page's root url is set to "admin/posts#index", and post creation works fine, except when I configure the routes file to redirect the user to root_url if he types "/admin/articles".
This is my routes file:
BlogDos::Application.routes.draw do
# Index
root to: "admin/posts#index"
# If I uncomment these two lines below, the post#create function doesn't work. When I
# submit the "new post" form, the controller just skips the function entirelly and
# redirects me to admin/posts#index without creating the new post.
# match "admin/posts" => redirect("/")
# match "admin/posts/" => redirect("/")
namespace :admin do
resources :cpanel
resources :posts do
resources :comments, :only => [:create, :destroy]
end
root to: "cpanel#index"
end
..
end
And this is my posts_controller.rb
def create
#usuario = current_user
#post = #usuario .posts.create(params[:post])
respond_to do |format|
if #post.save
format.html { redirect_to article_dir_path(#post.year, #post.month, #post.slug), notice: 'Article was successfully created.' }
format.json { render json: article_dir_path(#post.year, #post.month, #post.slug), status: :created, location: article_dir_path(#post.year, #post.month, #post.slug) }
else
format.html { render action: "new" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
Strangely, this only happens with the Create action, If i edit an article and update it, everything works fine.
I have sorted out almost everything from looking at Rails tutorials and QA websites, except this little problem, I'm sure it is something rather simple, but i'm new to Rails and not very familiar with its routing mechanics yet.
The form that creates the post submits to
/admin/posts
If you redirect that route to the index page, the controller action is never called.

Resources