API REST User Rails - ruby-on-rails

Hi I have a problem or do not know how to do it. I created a REST API . Here users_controller code for the API. I want to do so that when I create a new user or tested the same user ( login) is already in the database . When the same user in the database returns the error .
Please Help!:)
module Api
module V1
class UsersController < ApplicationController # Api::BaseController
before_filter :authenticate_user!, except: [:create, :index]
respond_to :json
def index
#respond_with
respond_to do |format|
format.html {render text: "Your data was sucessfully loaded. Thanks"}
format.json { render text: User.last.to_json }
end
end
def show
respond_with User.find(params[:id])
end
def create
respond_with User.create(login: params[:login],
email: params[:email],
password: params[:password],
spam: params[:spam],
male: params[:male],
facebookid: params[:facebookid]
)
end
def update
respond_with User.update(params[:id], params[:users])
end
def destroy
respond_with User.destroy(params[:id])
end
end
end
end

Please use the below code.
def create
#user=User.find_by_login(params[:login])
if #user.present?
render :status=>401, :json=> ["Login already present"]
else
respond_with User.create(login: params[:login],
email: params[:email],
password: params[:password],
spam: params[:spam],
male: params[:male],
facebookid: params[:facebookid]
)
render :status=>401, :json=> ["Login already present"]
end
end

Related

Rails API not able to destroy session

I am using Rails API and devise for authentication but when sending a request to destroy the session, it doesn't return any response other then status 200.It returns the same response no matter if the user exists, is logged in or the password is incorrect.
url http://localhost:3000/users/sign_in
I'm sending a DELETE request through Postman and it just returns a 200 response. It should be returning the data which is stored in the #message
{
"user":{
"email":"abc#abc.com",
"password":"abc#abc.com"
}
}
I even tried to destory the session using the session id:
curl -X DELETE -d "3" http://localhost:3000/users/sign_out
sessions_controller.rb
class API::V1::SessionsController < Devise::SessionsController
def create
#user = User.find_by_email(user_params[:email])
if #user && #user.valid_password?(user_params[:password])
session[:user_id]=#user.id
sign_in :user, #user
render json: #user
elsif #user && not(#user.valid_password?(user_params[:password]))
invalid_attempt
else
no_user
end
end
def destroy
#message = "signed out"
session.delete(:user_id)
sign_out(#user)
render json: #message
end
private
def no_user
render json: {error: "An account with this email doesn't exist. Please create a new one"}, status: :unprocessable_entity
end
def invalid_attempt
render json: { error: "Your password isn't correct" }, status: :unprocessable_entity
end
def user_params
params.require(:user).permit(:email, :password)
end
end
routes.rb
devise_for :users, controllers: { registrations: 'api/v1/registrations', sessions:'api/v1/sessions'}

Rails callback check if record exists, else return 404

I'm building an app where users can accept bookings from clients via their own booking page. These unique urls will all be public facing (no auth) and sent to potential clients by the user (this is how my client requested the functionality). When I enter an existing user's booking URL (e.g. https://localhost:3000/users/1/appointments/new) in the browser, the page works perfectly. When I enter the URL for a user that does not exist (e.g. https://localhost:3000/users/5999/appointments/new) I get the following error:
ActiveRecord::RecordNotFound in BookingsController#booking_page
Couldn't find User with 'id'=100
Instead of this error I would like to redirect to the 404 page instead. This is my controller (redirect_to_not_found is not being used, I was testing this in a before_action):
class BookingsController < ApplicationController
before_action :authenticate_user!, except: :booking_page
before_action :set_user, only: :booking_page
layout 'public', only: :booking_page
def booking_page
respond_to do |format|
if #user
format.html { render :booking_page }
format.json { render json: #user, status: :ok }
else
format.html { render(:file => Rails.root.join('public', '404'), :formats => [:html], :status => 404, :layout => false) }
format.json { render json: 'Not Fount', status: :not_found }
end
end
end
private
def redirect_to_not_found
respond_to do |format|
if #user == nil
format.html { render(:file => Rails.root.join('public', '404'), :formats => [:html], :status => 404, :layout => false) }
format.json { render json: 'Not Fount', status: :not_found }
end
end
end
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def bookings_params
params.require(:user_booking).permit(:client_firstname, :client_surname, :client_email, :client_mobile_namber, :services_required, :notes, :date, :start_time, :end_time, :location, :cost, :payment_completed)
end
end
Is there any way I can assign set the #user variable/object before running the booking_page action method and check if the user exists in the database at the same time?
I tried using the accepted answers from here but I still get the same error.
You can add this to your controller to rescue from this error/exception. You can put it in your ApplicationController for app-wide effect or in specific controllers.
rescue_from ActiveRecord::RecordNotFound do |exception|
logger.error "Not found ..."
redirect_to 404_path # You will have to configure this yourself in routes.rb
# ... OR use your method
redirect_to_not_found
end
User.find raises error when record is not in the DB. You can use nil-flavour of finders, e.g. find_by
#user = User.find_by(id: params[:id])
It will set #user to nil if it's not in the DB

Active Model Forbidden attributes error

would someone be able to help me understand this error. I am trying to create a contact form in rails following the building web apps tutorial. I followed the steps to generate a message scaffold. I then amended my routes. Next it said to put this into the messages controller show action.
if #message.save
flash[:notice] = 'Thanks for Your Message'
format.html { redirect_to root_path }
I have done this and i am getting the following error
ActiveModel::ForbiddenAttributesError in MessagesController#create
ActiveModel::ForbiddenAttributesError
This is my message controller file
class MessagesController < InheritedResources::Base
def show
if #message.save
flash[:notice] = 'Thanks for Your Message'
format.html { redirect_to root_path }
end
end
end
My routes file is as follows
# devise_for :users
resources :products do
resources :orders, only: [:new, :create]
#tells rails needs product id number
end
# get 'pages/payment'
get 'home/about'
get 'messages/new'
get 'seller' => "products#seller"
get 'sales' => "orders#sales"
get 'static_pages/productlanding'
get "content/veg"
get "content/fruit"
get "content/mix"
get 'subscriptions/new'
root 'static_pages#home'
Why are you saving in the show action?
--
Params
The ForbiddenAttributes error stems from the strong_params functionality of Rails.
When saving data, you're meant to pass the params through to your model through a strong_params method. This is typically achieved with the following setup:
#app/controllers/messages_controller.rb
class MessagesController < ApplicationController
def show
#message = Message.find(params[:id])
end
def new
#message = Message.new
end
def create
#message = Message.new(message_params)
#message.save
end
private
def message_params
params.require(:message).permit(:your, :message, :params)
end
end
This is how your controller should really be constructed. Your error, I believe, is caused by your lack of params to pass through to the attributes in your model (hence your call to #save resulting in trying to populate your model with non-data).
Strange. You execute saving method in "show" method of controller which responsible for showing up the content on the separate page.
You should replace as following:
def create
if #message.save
flash[:notice] = 'Thanks for Your Message'
format.html { redirect_to root_path }
end
end
i have managed to sort this with the following! Thanks for all the help
class MessagesController < ApplicationController
before_action :set_message, only: [:show, :edit, :update, :destroy]
# GET /messages
# GET /messages.json
def index
#messages = Message.all
end
# GET /messages/1
# GET /messages/1.json
def show
end
# GET /messages/new
def new
#message = Message.new
end
# GET /messages/1/edit
def edit
end
# POST /messages
# POST /messages.json
def create
#message = Message.new(message_params)
respond_to do |format|
if #message.save
flash.now[:notice] = 'Thank you for your message!'
format.html { redirect_to root_path }
format.json { render :show, status: :created, location: #message }
else
format.html { render :new }
format.json { render json: #message.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /messages/1
# PATCH/PUT /messages/1.json
def update
respond_to do |format|
if #message.update(message_params)
format.html { redirect_to #message, notice: 'Message was successfully updated.' }
format.json { render :show, status: :ok, location: #message }
else
format.html { render :edit }
format.json { render json: #message.errors, status: :unprocessable_entity }
end
end
end
# DELETE /messages/1
# DELETE /messages/1.json
def destroy
#message.destroy
respond_to do |format|
format.html { redirect_to messages_url, notice: 'Message was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_message
#message = Message.find(params[:id])
end
.
def message_params
params.require(:message).permit(:name, :email, :company, :phone, :subject, :body)
end
end
I was facing this same error. The fix was to make the params function name same as the root tag of the post json like below
Post json
{"jobseeker_certificate":{"id":-1,"name":"First Class Medical Certificate","institute":"GACA","attachment":null}}
In Controller i changed jobseeker_aircraft_type_ratings_params to jobseeker_certificate_params
def jobseeker_certificate_params
params.require(:jobseeker_certificate).permit(:aircraft, :total_time, :pilot_in_command,
:co_pilot, :rating_expiry_date, :from, :to, :jobseeker_id, :grade, :institute, :attachment, :name,
:from, :to, :jobseeker_id, :grade, :institute, :attachment, :name, :sector_id, :certificate_type,
:details, :certificate_type, :details)
end

Ruby on rails "Could find user with id= create"

i don't know what's wrong, I tried to add "create" method to my application, and what i get is :
"ActiveRecord::RecordNotFound in UsersController#show"
"Couldn't find User with id=create"
And then code
# Use callbacks to share a common setup
def set_user
#user = User.find(params[:id])
end
# Permit only specific parameters
here's my User controller
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def index
#users = User.all
end
def show
end
def create
#user = User.new(user_params)
respond_to do |user|
if #user.save(user_params)
user.html { redirect_to users_path, :notice => "User has been created!" }
else
user.html { redirect_to create_user_path(#user), :notice => "Sorry, couldn't create user. Try again!" }
end
end
end
def edit
end
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to users_path, :notice => "User has been updated!" }
else
format.html { redirect_to edit_user_path(#user), :notice => "Sorry, couldn't update user. Try again!" }
end
end
end
def destroy
#user.destroy
respond_to do |d|
d.html { redirect_to users_path, :notice => "User has been successfully destroyed :C !" }
end
end
private
# Use callbacks to share a common setup
def set_user
#user = User.find(params[:id])
end
# Permit only specific parameters
def user_params
params.require(:user).permit(:name, :email)
end
end
The thing is, the index page works perfectly fine, but if i try to go somewhere else, like /users/create i get that error.. I tried changing routes, rewriting the code, nothing helps.My routes are like this:
# Root '/'
root "users#index"
# Show Users
get "users/:id" => "users#show"
Can you guys help me ? I am literally stuck, as to how fix that problem :c
This should help you - you're missing resources :users, which creates a set of RESTful routes for your controller. This, combined with the other answers should help
You don't go to the create action via a URL. It's there to create a new user coming back from the new.html.erb file.
If you want to create a new user you could use /users/new and add a new method to your controller along the lines of:
def new
#user = User.new
end
You will also need to change your routes.rb file to add all the default actions like:
resources :users
I suggest you work through http://guides.rubyonrails.org/getting_started.html.
In your controller:
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def index
#users = User.all
end
def show
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to users_path, :notice => "User has been created!"
else
render :new
end
end
def edit
end
def update
if #user.update(user_params)
redirect_to users_path, :notice => "User has been updated!"
else
render :edit
end
end
def destroy
#user.destroy
redirect_to users_path, :notice => "User has been successfully destroyed :C !" }
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :email)
end
end
You are using all RESTful actions, so you can add to routes.rb:
resources :users
And remove this:
get "users/:id" => "users#show"

CanCan load_and_authorize_resource triggers Forbidden Attributes

I have a standard RESTful controller that uses strong parameters.
class UsersController < ApplicationController
respond_to :html, :js
def index
#users = User.all
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def edit
#user = User.find(params[:id])
end
def create
#user = User.new(safe_params)
if #user.save
redirect_to #user, notice: t('users.controller.create.success')
else
render :new
end
end
def update
#user = User.find(params[:id])
if #user.update_attributes(safe_params)
redirect_to #user, notice: t('users.controller.update.success')
else
render :edit
end
end
def destroy
#user = User.find(params[:id])
if current_user != #user
#user.destroy
else
flash[:error] = t('users.controller.destroy.prevent_self_destroy')
end
redirect_to users_url
end
private
def safe_params
safe_attributes =
[
:first_name,
:last_name,
:email,
:password,
:password_confirmation,
]
if current_user.is?(:admin)
safe_attributes += [:role_ids]
end
params.require(:user).permit(*safe_attributes)
end
end
In my config/initializers I have the file strong_parameters.rb
ActiveRecord::Base.send(:include, ActiveModel::ForbiddenAttributesProtection)
When I add a simple call to CanCan's load_and_authorize_resource I get
1) UsersController POST create with invalid params re-renders the 'new' template
Failure/Error: post :create, user: #attr
ActiveModel::ForbiddenAttributes:
ActiveModel::ForbiddenAttributes
# ./spec/controllers/users_controller_spec.rb:128:in `block (4 levels) in <top (required)>'
Where #attr in the test is defined as
before(:each) do
#attr =
{
first_name: "John",
last_name: "Doe",
email: "user#example.com",
password: "foobar",
password_confirmation: "foobar"
}
end
In the tests I have it all setup properly to login the user and give them the necessary roles for being an administrator so I know it's not that. I don't know why this is causing ForbiddenAttributes to trigger. I'm sure it's something simple I've overlooked. Has anyone else encountered this problem and found a solution to it?
I believe this is because CanCan will use its own getter method for the requested resource if you don't pre-load it with a before_filter. So you could add this to the controller and it should work:
class UsersController < ApplicationController
before_filter :new_user, :only => [:new, :create]
load_and_authorize_resource
def new_user
#user = User.new(safe_params)
end
end
(And then do the same for the edit/update actions.)
before_filter do
params[:user] = safe_params
end
load_and_authorize_resource

Resources