I'm trying to create an API, but I get the error
"type": "NameError",
"message": "uninitialized constant Api::V1::ReservationOptionsController::ReservationOptions",
I cannot seem to find the issue here.
Code
routes
namespace :api, defaults: { format: :json } do
namespace :v1 do
resources :reservation_options, only: [:show, :create]
end
end
controllers/api/v1/reservation_options_controller.rb
class Api::V1::ReservationOptionsController < Api::V1::BaseController
acts_as_token_authentication_handler_for User, only: [:create]
def show
#reservation_option = ReservationOption.find(params[:id])
#reservation = #reservation_option.reservation
authorize #reservation_option
end
def create
#user = current_user
#reservation_option = ReservationOptions.new(reservation_option_params)
authorize #reservation_option
if #reservation_option.save
render :show, status: :created
else
render_error
end
end
private
def reservation_option_params
params.require(:reservation_option).permit(:option_id, :option_quantity, :reservation_id)
end
end
You have an error in the action create
def create
#user = current_user
# change this line
# #reservation_option = ReservationOptions.new(reservation_option_params)
#reservation_option = ReservationOption.new(reservation_option_params)
authorize #reservation_option
if #reservation_option.save
render :show, status: :created
else
render_error
end
end
It looks like ReservationOptions hasn't been defined anywhere, and you're using it in controllers/api/v1/reservation_options_controller.rb.
Make sure you've spelled it right, or that you have the appropriate model in app/models/reservation_option.rb. My guess is that it should be ReservationOption, since Rails model class names are typically singular.
Related
Im trying to pass a client_id parameter from one of my views to a different models controller, but it seems like the param isn't being passed since I get the error "undefined method `client_id=' for nil:NilClass" in the set_client method. What am I doing wrong? ANy help would be appreciated. Thanks
<%= link_to 'New assessment', new_assessment_path(:client_id => #client.id), class: "btn btn-xs btn-success" %>
This is my controller:
class AssessmentsController < ApplicationController
before_action :set_assessment, only: [:show, :edit, :update, :destroy]
before_action :set_client, only: [:new]
def new
#assessment = Assessment.new
end
def create
#assessment = Assessment.new(assessment_params)
respond_to do |format|
if #assessment.save
format.html { redirect_to #assessment, notice: 'Assessment was successfully created.' }
format.json { render :show, status: :created, location: #assessment }
else
format.html { render :new }
format.json { render json: #assessment.errors, status: :unprocessable_entity }
end
end
end
def set_client
#assessment.client_id = params[:client_id]
end
Routes:
Rails.application.routes.draw do
resources :trainers
resources :clients
resources :assessments
root 'pages#home'
Main Reason for the undefined error is You are passing client_id to new method but not to the create method.
And What i understood from ur question is You want add a assessment to a client.
If this is your goal follow these steps
1.create association in respective models.
add the following line in Client.rb
has_many: :assesments
and add in Assement.rb
belongs_to: Client
2.Now change ur routes.rb.
resources clients do
resources assements do
end
end
3.Now check ur routes by executing this cmd rake routes
now your routes should be like this
/clients/:client_id/assements/new(.:format)
4.Now you dont need to pass the client id param manually.
Hope this will help you in solving ur problem.
cmt here if any..
Your error reads:
undefined method `client_id=' for nil:NilClass
That's coming from:
def set_client
#assessment.client_id = params[:client_id]
end
Which is being called before your new action due to:
before_action :set_client, only: [:new]
At that point, #assessment is nil in set_client because you haven't yet assigned the variable. Thus the error.
It has nothing to do with params not passing.
My suggestion is, remove the before_action and change the new action to:
def new
#assessment = Assessment.new(client_id: params[:client_id])
end
Do Assessment.find_by(client_id: params[:client_id]) in your set_client method.
You are trying to set the client_id in #assessment, and that variable is not defined when you are trying to set it.
before_action's callback is executed, as the name says, before the action (AKA method).
You should remove the before_action and add the setter within your new method
def new
#assessment = Assessment.new
#assessment.client_id = params[:client_id]
end
1.Set client in before_action
2.no need to create #assesment in new method
Change as below
class AssessmentsController < ApplicationController
before_action :set_assessment, only: [:show, :edit, :update, :destroy]
before_action :set_client, only: [:new]
def new
end
def create
#assessment = Assessment.new(assessment_params)
respond_to do |format|
if #assessment.save
format.html { redirect_to #assessment, notice: 'Assessment was successfully created.' }
format.json { render :show, status: :created, location: #assessment }
else
format.html { render :new }
format.json { render json: #assessment.errors, status: :unprocessable_entity }
end
end
end
def set_client
#client_id = Client.find_by(params[:client_id])
end
end
I am new to build Rails API from scratch (only API not web app) so I can build iOS app to connect to API. What I have an issue on my Rails API project doesn't allow me to have return JSON results, it always return HTML. Any idea what is wrong? Any suggestion appreciated. Thanks!
What I want to have like this:
{"code":12,"title":"User doesn't exist","status":404}
This is what I got (it returns in red header in HTML page):
ActiveRecord::RecordNotFound in Api::V1::UsersController#show
Couldn't find User with 'id'=5
Take a look at my scripts:
routes.rb (require JSON format):
Rails.application.routes.draw do
namespace :api, defaults: { format: :json } do
namespace :v1 do
resources :entries, except: [:new, :edit]
resources :users, except: [:new, :edit]
end
end
end
../app/controllers/api/v1/users_controller.rb
module Api
module V1
class UsersController < ApplicationController
before_action :set_user, only: [:show, :update, :destroy]
def show
if User.exists?(params[:id])
#user = User.find(params[:id])
render json: #user
else
render json: { code: 12, title: "User doesn't exist", status: 404 }, status: :not_found
end
.
.
.
Note: It is very strange how this show method above acting weird. Part 1 is working well to return JSON results but Part 2 returns HTML instead JSON results.
Part 1: render json: #user
Part 2: render json: { code: 12, title: "User doesn't exist", status: 404 }, status: :not_found
../app/controllers/api/v1/application_controller.rb
class ApplicationController < ActionController::API
rescue_from ActionController::ParameterMissing, with: :render_bad_request
rescue_from ActiveRecord::RecordNotSaved, :with => :access_denied
def render_bad_request(e)
render json: params, status: :bad_request
end
end
Use User.where(id: params[:id]).first instead User.exists?(). Is the same query and it going to be cached by Active Record.
Also, i think that you before_action method is the guilty. Try with this
protected
def set_user
#user ||= User.where(id: params[:id]).first
end
...
And in your controller
def show
if #user.present?
render json: #user
else
render json: { code: 12, title: "User doesn't exist", status: 404 }, status: :not_found
end
I am getting a routing error when I attempt to create a new db entry or update a current one.
ERROR: No route matches [POST] "/pubs"
Routes.rb:
resources :people, except: [:show] do
resources :pubs, except: [:create, :new, :edit, :destroy]
end
resources :articles
resources :pubs, except: [:create, :new, :edit, :destroy]
namespace :sekret do
resources :people do
resources :pubs
end
end
sekret/pubs_controller
class Sekret::PubsController < SekretController
def index
#pubs = Pub.all
end
def show
#pub = Pub.find(params[:id])
end
def new
#person = Person.find(params[:person_id])
#pub = #person.pubs.new
end
def create
#pub = Pub.new(pub_params)
if #pub.save
flash[:notice] = "Article created successfully!"
redirect_to sekret_person_pub_path(#pub)
else
render :new, status: :unprocessable_entity
end
end
def edit
#pub = Pub.find(params[:id])
end
def update
#pub = Pub.find(params[:id])
if #pub.update(pub_params)
redirect_to sekret_person_pub_path(#pub)
else
render :edit, status: :unprocessable_entity
end
end
def destroy
pub = Pub.find(params[:id])
pub.destroy
redirect_to sekret_people_path
end
private
def pub_params
params.require(:pub).permit(
:pubmed_id, :journal, :pages, :date, :type, :link, :authors,
:title, :notes, :auth_id, :person_id)
end
end
After going through all of this setup, when I allow the non-namespace pubs to resolve edit, update, etc, the update process goes through without a hitch. Once I limit these functions to within the password protected namespace I get the routing error. After parsing through the routes I can see that sekret_person_pub_path is listed there. I think I am missing something somewhere.
Rake Routes:
pubs#index
pub GET /pubs/:id(.:format) pubs#show
PATCH /pubs/:id(.:format) pubs#update
PUT /pubs/:id(.:format) pubs#update
sekret_person_pubs GET /sekret/people/:person_id/pubs(.:format) sekret/pubs#index
POST /sekret/people/:person_id/pubs(.:format) sekret/pubs#create
new_sekret_person_pub GET /sekret/people/:person_id/pubs/new(.:format) sekret/pubs#new
edit_sekret_person_pub GET /sekret/people/:person_id/pubs/:id/edit(.:format) sekret/pubs#edit
sekret_person_pub GET /sekret/people/:person_id/pubs/:id(.:format) sekret/pubs#show
PATCH /sekret/people/:person_id/pubs/:id(.:format) sekret/pubs#update
PUT /sekret/people/:person_id/pubs/:id(.:format) sekret/pubs#update
DELETE /sekret/people/:person_id/pubs/:id(.:format) sekret/pubs#destroy
sekret_people GET /sekret/people(.:format)
By using resources :pubs, except: [:create, :new, :edit, :destroy], you are preventing the route generation from providing POST /pubs.
The namespace and nested resources will generate a URL POST sekret/people/:person_id/pubs.
In your controller, you should create the Pub as an associated object.
def create
person = Person.find(params[:person_id])
#pub = person.pubs.new(pub_params)
if #pub.save
flash[:notice] = "Article created successfully!"
redirect_to sekret_person_pub_path(#pub)
else
render :new, status: :unprocessable_entity
end
end
If you want to restrict access the create method, you could use an authorization library such as Pundit in which case you would setup a policy to restrict who can do what.
https://github.com/elabs/pundit
You are missing out on the routes because rails form don't use the correct routes when namespacing so you'll have to specify them manually
<%= form for #pub, url: sekret_person_pubs_path do |f| %>
to let the form knows which route to post, if you do not specify the url, rails will use url: person_pubs_path behind the scenes
Edit: forgot to add _path
I'm testing some gems since I'm about to create an API for a iOS app. This time I'm using Rails-API and Devise for user registrations. I followed this gist that I forked from a forked-forked gist, I did some changes and a User can register and login, but, when I use before_filter :authenticate_api_user! on a controller, after login the current_api_user is nil. According to this from the source code of divise, I a use devise_for inside a namespace then everything changes. This is my code.
Routes:
Todo::Application.routes.draw do
namespace :api do
devise_for :users
resources :users, only: [:index, :show]
resources :videos, only: [:create]
get "/users/show", to: "users#show"
end
end
app/api/sessions_controller.rb
class Api::SessionsController < ApplicationController
before_filter :authenticate_api_user!, except: [:create]
before_filter :ensure_user_login_param_exists, only: [:create]
# before_filter :ensure_email_param_exists, only: [:create]
# before_filter :ensure_password_param_exists, only: [:create]
respond_to :json
def create
resource = User.find_for_database_authentication(email: params[:user_login][:email])
return invalid_login_attempt unless resource
if resource.valid_password?(params[:user_login][:password])
sign_in(:api_user, resource)
#resource.ensure_authentication_token!
render json: { success: true, email: current_api_user.email }, status: :created
return
end
invalid_login_attempt
end
.
.
.
end
app/api/registrations_controller.rb
class Api::RegistrationsController < ApplicationController
respond_to :json
def create
user = User.new(user_params)
if user.save
render json: user.as_json(email: user.email), status: :created
return
else
warden.custom_failure!
render json: user.errors, status: :unprocessable_entity
end
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
end
I hope someone can help me. By the way I'm really accepting any advice about the best way to create an API using rails. It's my first time.
Thank you in advance.
I get an error when I try to visit the below url in my rails app.
http://localhost:3000/origtexts/1/reviews/new
routes.rb
resources :origtexts do
resources :reviews
end
It passes the param of the review (1) correctly but I the error I get is undefined method `review' for the line in ReviewsController#new.
reviews_controller.rb
class ReviewsController < ApplicationController
before_filter :find_origtext
before_filter :find_review, :only => [:show, :edit, :update, :destroy]
def new
#review = #origtext.review.build
end
def show
end
def create
#review = #origtext.reviews.build(params[:review])
if #review.save
flash[:notice] = 'Review has been created'
redirect_to [#origtext, #review]
else
flash[:alert] = 'Review has not been created'
render :action => 'new'
end
end
private
def find_origtext
#origtext = Origtext.find(params[:origtext_id])
end
def find_review
#review = #origtext.reviews.find(params[:id])
end
end
Any advice on how to fix this?
Change review to reviews in this line
#review = #origtext.review.build
To
#review = #origtext.reviews.build