Rails 4 - Nested resources - REST API render json error - ruby-on-rails

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.

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

Rails api with paperclip

I have rails api with simple paperclip model:
def create
#photo = Photo.new(photo_params)
if #photo.save
render json: #photo, status: :created, location: #photo
else
render json: #photo.errors, status: :unprocessable_entity
end
end
private
def photo_params
params.require(:photo).permit(:image, :title)
end
My frontend framework send get like this
{"title"=>"simpletitletext", "photo"=>{"image"=>......}}
But it wrong, because rails waits following
{"photo"=>{"title"=>"simpletitle", "image"=>#...}}
I had been trying for different ways to fix angular for many hours, before wrote . May be it will be able to fix in rails
If your server has an incoming request that looks like this:
{"title"=>"simpletitletext", "photo"=>{"image"=>......}}
you can make it look like this:
{"photo"=>{"title"=>"simpletitle", "image"=>#...}}
The only difference between the two is that in the first, the title key is outside of the photo nested hash. but you want it to be inside.
So in your Rails controller,. you could write:
def photo_params
hash = params[:photo]
hash.merge(title: params[:title])
end

:id => "info" error rails wicked forms when retrieving params

I'm new to wicked form and I was following the railcast episode on wicked forms but I keep receiving this error "Couldn't find Company with 'id'=info". So I know that the problem is clearly in my controllers somewhere. I know it's something super simple that I'm just racking my brain on so I know you guys will be a giant help. Here is the code, any and all help appreciated!
Code for companies Controller:
def create
#company = Company.new(company_params)
respond_to do |format|
if #company.save
#object = #company.id
format.html { redirect_to(company_steps_path(#company)) }
format.json { render :show, status: :created, location: #company }
else
format.html { render :new }
format.json { render json: #company.errors, status: :unprocessable_entity }
end
end
end
Code for company_steps Controller:
class CompanyStepsController < ApplicationController
include Wicked::Wizard
steps :info, :address, :quote
def show
#company = Company.find(params[:id])
render_wizard
end
def update
#company = Company.where(id: params[:id])
#company.attributes = params[:company]
render_wizard #company
end
end
When you use #find and the record is not found ActiveRecord raise a ActiveRecord::RecordNotFound with a message like "Couldn't find Company with id='somevalue'".
I assume your id column is of type integer and you pass a string.
In your #show method params[:id] == 'info'.
Check your link_to, redirect_to and routes.
At some point you generate this url http://localhost:3000/company_steps/info (probably in a view).
You do a GET request on it, which match GET "/company_steps/:id" company_steps#show.
The method #show is call in the controller CompanyStepsController with params[:id] == 'info'.
As we see previously you get a ActiveRecord::RecordNotFound exception because ActiveRecord can't find the record with a id 'info'.
The error is raise in your controller, but the problem is probably in your views or in a redirect. You need a id and you pass a string.
EDIT: as discussed in comments
Ok params[:id] == 'info' is generated by wicked.
They use id to control the flow of steps.
You need to use nested routes to have rails generate something like params[:company_id].
resources :companies do
resources :steps, controller: 'companies/steps'
end
So rake routes should give you:
/companies/:company_id/steps/:id
in the controller
params[:company_id] == 42
params[:id] == 'info'
https://github.com/schneems/wicked/wiki/Building-Partial-Objects-Step-by-Step

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 Test post Request with firefox plugin results in bad request

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

Resources