I have a really strange error, when i submit my form to create a new admin i get this error:
NoMethodError in AdminsController#create
undefined method `admin?' for #<Admin:0x6c7f098>
in line:
if #admin.save
How is this error produced? I mainly used scaffold code and i only deletet the views of the controller! Here is my controller: I thank everybody for help!
class AdminsController < ApplicationController
before_action :set_admin, only: [ :edit, :update, :destroy]
# GET /admins/new
def new
#admin = Admin.new
end
# GET /admins/1/edit
def edit
end
# POST /admins
# POST /admins.json
def create
#admin = Admin.new(admin_params)
respond_to do |format|
if #admin.save
format.html { redirect_to adminpage_index_path, notice: 'Admin was successfully created.' }
else
redirect_to adminpage_index_path
end
end
end
# PATCH/PUT /admins/1
# PATCH/PUT /admins/1.json
def update
respond_to do |format|
if #admin.update(admin_params)
format.html { redirect_to adminpage_index_path , notice: 'Admin was successfully updated.' }
format.json { head :no_content }
else
redirect_to adminpage_index_path
end
end
end
# DELETE /admins/1
# DELETE /admins/1.json
def destroy
#admin.destroy
respond_to do |format|
format.html { redirect_to adminpage_index_path }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_admin
#admin = Admin.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def admin_params
params.require(:admin).permit(:username, :vorname, :nachname, :strasse, :ort, :plz, :telefon, :handy, :email, :password, :password_confirmation)
end
end
From what I can see, your Admin model probably does not inherit from ActiveRecord::Base. Make sure it does. The model should look like this:
class Admin < ActiveRecord::Base
# ...
end
Your admin model has a callback of some kind. i.e. before_save, after_save, after_validations. Something like that that is trying to call admin?
Post admin.rb file and the stack trace of the error and this should be easy to find.
Related
So in my project Project is parent and Medium is Child.
I want to delete one of the childs asynchronously (ajax / js.erb).
When clicking on this link (turbo_method is supposed to imply the asynchronous part of the request but I'm not sure about how it works.) something goes wrong.
<%= link_to "Delete Medium", project_medium_path(medium.project, medium), data: { turbo_method: :delete, turbo_confirm: 'are you sure ?' } %>
Here are my logs.
My problem is that after deleting my media entity, it also deletes my project entity. The fact that deleting my project entity implies a ForeignKeyViolation error is normal, I haven't setup my model correctly yet. Either way, it shouldn't delete my project entity.
Here are my controllers, models and my views disposition :
Projects controller
class ProjectsController < ApplicationController
before_action :set_project, only: %i[ show edit update destroy ]
# GET /projects
def index
#projects = policy_scope(Project).order(date: :desc)
authorize Project
end
# GET /projects/1
def show
#medium = Medium.new(project: #project)
end
# GET /projects/new
def new
#project = Project.new
# Set active user as project owner
#project.user = current_user
authorize #project
end
# GET /projects/1/edit
def edit
end
# POST /projects
def create
#project = Project.new(project_params)
# Set active user as project owner
#project.user = current_user
authorize #project
respond_to do |format|
if #project.save
format.html { redirect_to project_url(#project), notice: "Project was successfully created." }
else
format.html { render :new, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /projects/1
def update
respond_to do |format|
if #project.update(project_params)
format.html { redirect_to project_url(#project), notice: "Project was successfully updated." }
else
format.html { render :edit, status: :unprocessable_entity }
end
end
end
# DELETE /projects/1
def destroy
#project.destroy
respond_to do |format|
format.html { redirect_to projects_url, notice: "Project was successfully destroyed." }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_project
#project = Project.find(params[:id])
authorize #project
end
# Only allow a list of trusted parameters through.
def project_params
params.require(:project).permit(:title, :slug, :subject, :category, :description, :location, :date, :user_id)
end
end
Media controller
class MediaController < ApplicationController
before_action :set_medium, only: %i[ edit update destroy ]
before_action :set_project, only: %i[ create edit update ]
# GET /media
# def index
# end
# GET /media/1
#def show
#end
# GET /media/new
def new
#medium = Medium.new
authorize #medium
end
# GET /media/1/edit
def edit
end
# POST /media
def create
#medium = #project.media.create(medium_params)
authorize #medium
respond_to do |format|
if #medium.save
format.html { redirect_to project_url(#medium.project), notice: "Medium was successfully created." }
format.js
else
format.html { render :new, status: :unprocessable_entity }
format.js
end
end
end
# PATCH/PUT /media/1
def update
respond_to do |format|
if #medium.update(medium_params)
format.html { redirect_to project_url(#medium.project), notice: "Medium was successfully updated." }
else
format.html { render :edit, status: :unprocessable_entity }
end
end
end
# DELETE /media/1
def destroy
#project = #medium.project
#medium.destroy
respond_to do |format|
format.html { redirect_to #project, notice: "Medium was successfully destroyed." }
format.js
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_project
#project = Project.find(params[:project_id])
authorize #project
end
# Use callbacks to share common setup or constraints between actions.
def set_medium
#medium = Medium.find(params[:id])
authorize #medium
end
# Only allow a list of trusted parameters through.
def medium_params
params.require(:medium).permit(:title, :description, :author, :location, :date, :priority_index, :project_id, :visual)
end
end
Project model
Medium model
Thanks for the help !
I found a solution through this post.
Using status: 303 inside Media#Destroy for the redirect_to method.
My ruby application is throwing an error which has appeared all of a sudden. the error thrown is NoMethodError in JobsDevsController # listing=> undefined method `user_id' for nil:NilClass
The part of my code that throws this error in my controller is
def is_authorised
redirect_to root_path, alert: "You don't have permission..." unless current_user.id == #job.user_id
end
My Controller
class JobsDevsController < ApplicationController
before_action :set_jobs_dev , except: [:index, :new, :create, :show, :edit, :listing]
before_action :authenticate_user!, except: [:show, :listing]
before_action :is_authorised, only: [:listing, :budget, :description, :photo_upload, :location, :update, :show ]
# GET /jobs_devs
def index
#jobs_devs = JobsDev.all
end
# GET /jobs_devs/1
def show
end
# GET /jobs_devs/new
def new
#jobs_dev = current_user.jobs_devs.build
end
# def listing
# #jobs_dev = current_user.jobs_dev
# end
# GET /jobs_devs/1/edit
def edit
end
def budget
end
# POST /jobs_devs
def create
#jobs_dev = current_user.jobs_devs.build(jobs_dev_params)
if #jobs_dev.save!
redirect_to listing_jobs_dev_path(#jobs_dev), notice: 'Jobs dev was successfully created.'
else
render :new
end
end
# PATCH/PUT /jobs_devs/1
# def update
# if #jobs_dev.update(jobs_dev_params)
# redirect_to #jobs_dev, notice: 'Jobs dev was successfully updated.'
# else
# render :edit
# end
# end
def update
respond_to do |format|
if #jobs_dev.update(jobs_dev_params)
format.html { redirect_to #jobs_dev, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #jobs_dev }
else
format.html { render :edit }
format.json { render json: #jobs_dev.errors, status: :unprocessable_entity }
end
end
end
# DELETE /jobs_devs/1
def destroy
#jobs_dev.destroy
redirect_to jobs_devs_url, notice: 'Jobs dev was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_jobs_dev
#jobs_dev = JobsDev.find(params[:id])
end
def is_authorised
redirect_to root_path, alert: "You don't have permission..." unless current_user.id == #jobs_dev.user_id
end
# Only allow a trusted parameter "white list" through.
def jobs_dev_params
params.require(:jobs_dev).permit(:job_category, :job_type, :job_title, :job_description, :recurrence,
:budget, images: []
)
end
end
Please can you help with this senario
Make sure you set_job for listing actiton
You may need to add to the listing action directly
#job = current_user.job
or the better way to add it to before action of listing action and take order into consideration
Looks like your is_authorised method is looking for #job, which isn't set in your controller; rather, you assign #jobs_dev.
Update the method to the following:
def is_authorised
redirect_to root_path, alert: "You don't have permission..." unless current_user.id == #jobs_dev.user_id
end
I'm not sure that's sufficient, as you're skipping setting this in your before_action:
before_action :set_jobs_dev , except: [:index, :new, :create, :show, :edit, :listing]
It looks as if you'll need to remove :listing from the except clause there.
Try both of these things and it should work again. Let me know if you've any questions or have any issues with this :)
I'm trying to make a very simple web app using Rails and I'm using the Sorcery gem to authenticate users. I followed the tutorial here on their GitHub page, and I'm getting no where with it.
I have 2 issues which I believe are probably linked.
The first being, when I use this before_filter skip_before_filter :require_login, only: [:index, :new, :create], users can still access the page without logging in.
The other issue is, when a user tries to log in, they aren't redirected, and when I use the built in helper logged_in?, it always returns false. Even though there was no error message when logging in.
I've added the appropriate controllers, let me know if you need to look at anything else.
Thanks.
user_sessions_controller.rb
class UserSessionsController < ApplicationController
skip_before_filter :require_login, :except => [:destroy]
def new
#user = User.new
end
def create
if #user = login(params[:email], params[:password])
redirect_back_or_to(:users, :notice => 'Login successfull.')
else
flash.now[:alert] = 'Login failed'
render action: 'new'
end
end
def destroy
logout
redirect_to(:users, :notice => 'Logged out!')
end
end
users_controller.rb
class UsersController < ApplicationController
skip_before_filter :require_login, only: [:index, :new, :create]
# GET /users
# GET /users.json
def index
#users = User.all
end
# GET /users/1
# GET /users/1.json
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to :users, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# 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 user_params
# params.require(:user).permit(:email, :crypted_password, :salt)
#end
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
end
application_controller.rb
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
# protect_from_forgery with: :exception
protect_from_forgery
before_filter :require_login
private
def not_authenticated
redirect_to(login_path, :alert => "Please login first")
end
end
Everyone has access to Users pages due to this line skip_before_filter :require_login, only: [:index, :new, :create]. This literally means "don't check authorization". Just remove this line.
Generally you should skip require_login filter only on public pages and login pages (i.e. UserSessionsController#create etc).
And the second issue: do you have authenticates_with_sorcery! in your User model?
I am coding a Ruby on Rails app (rails 4), on an ubuntu machine.
I have created a new scaffold (model/view/controller) via rails g scaffold common_warnings , and it works just fine on my local machine (localhost:3000/common_warnings resolves to something appropriate), however when I upload this to my server, I get this error:
ActionController::RoutingError (uninitialized constant CommonWarningsController)
when trying to get mydomain.com/common_warnings.
I know that sometimes pluralization is a problem, these are the first lines of each of my controller and model files:
app/controllers/common_warnings_controller.rb
class CommonWarningsController < ApplicationController
app/models/common_warning.rb
class CommonWarning < ActiveRecord::Base
My rails app already has 30something tables in the database, I know I did have this problem a while ago but just can't work out how to fix this one. The pluralization seems to match what I do for loan_histories_controller.rb (also a multi-word name).
The output of rake routes is the same on my local machine and on the server. This is the relevant output:
rake routes | grep common
common_warnings GET /common_warnings(.:format) common_warnings#index
POST /common_warnings(.:format) common_warnings#create
new_common_warning GET /common_warnings/new(.:format) common_warnings#new
edit_common_warning GET /common_warnings/:id/edit(.:format) common_warnings#edit
common_warning GET /common_warnings/:id(.:format) common_warnings#show
PATCH /common_warnings/:id(.:format) common_warnings#update
PUT /common_warnings/:id(.:format) common_warnings#update
DELETE /common_warnings/:id(.:format) common_warnings#destroy
"The server" in this case is provided by AWS
This is my complete common warnings controller:
class CommonWarningsController < ApplicationController
before_action :set_common_warning, only: [:show, :edit, :update, :destroy]
before_action :signed_in_user
before_action :admin_user
# GET /common_warnings
# GET /common_warnings.json
def index
#common_warnings = CommonWarning.all
end
# GET /common_warnings/1
# GET /common_warnings/1.json
def show
end
# GET /common_warnings/new
def new
#new_or_edit = 'new'
#common_warning = CommonWarning.new
end
# GET /common_warnings/1/edit
def edit
#new_or_edit = 'edit'
end
# POST /common_warnings
# POST /common_warnings.json
def create
#common_warning = CommonWarning.new(common_warning_params)
respond_to do |format|
if #common_warning.save
format.html { redirect_to #common_warning, notice: 'Common warning was successfully created.' }
else
format.html { render action: 'new' }
end
end
end
# PATCH/PUT /common_warnings/1
# PATCH/PUT /common_warnings/1.json
def update
respond_to do |format|
if #common_warning.update(common_warning_params)
format.html { redirect_to #common_warning, notice: 'Common warning was successfully updated.' }
else
format.html { render action: 'edit' }
end
end
end
# DELETE /common_warnings/1
# DELETE /common_warnings/1.json
def destroy
#common_warning.destroy
respond_to do |format|
format.html { redirect_to common_warnings_url }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_common_warning
#common_warning = CommonWarning.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def common_warning_params
params.require(:common_warning).permit(:name)
end
def signed_in_user
store_location
redirect_to signin_url, notice: "Please sign in." unless signed_in?
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
Thanks in advance!
Fixed. It was a complicated problem to do with having multiple similar but not identical rails apps running from one server. I had forgotten to reset the connection to the schema migrations. Thanks to those who responded!
I'm pretty new to rails and I'm just now developing my first rails app, so this might be a dumb question to some. I would like to let the current_user see only their own orders if they are not an admin. I was able to set only admins can see all orders, but I'm having a hard time enabling current user to see, list and delete only their own orders. My app has a :orders model that belongs_to :users and a :users model with has_many :orders.
This is how my orders_controller.rb look like:
class OrdersController < ApplicationController
before_action :set_order, only: [:show, :edit, :update, :destroy]
# GET /orders
# GET /orders.json
def index
authorize! :index, #user, :message => 'Not authorized as an administrator.'
#orders = Order.all
end
# GET /orders/1
# GET /orders/1.json
def show
end
# GET /orders/new
def new
#order = Order.new
end
# GET /orders/1/edit
def edit
end
# POST /orders
# POST /orders.json
def create
#order = Order.new(order_params)
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render action: 'show', status: :created, location: #order }
else
format.html { render action: 'new' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /orders/1
# PATCH/PUT /orders/1.json
def update
respond_to do |format|
if #order.update(order_params)
format.html { redirect_to #order, notice: 'Order was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# DELETE /orders/1
# DELETE /orders/1.json
def destroy
#order.destroy
respond_to do |format|
format.html { redirect_to orders_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order
#order = Order.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_params
params.require(:order).permit(:user_id, :drop_address)
end
end
My question is how do I allow only the current user to list and see all orders made by them only?
Thanks
There is gem named cancan for you.
Please read wiki page.
Need more help? let me know :)
define ability
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, :all
else
can :read, Order, :user_id => user.id
end
end
end
from controller query by accessible_by
#orders = Order.accessible_by(current_ability)
you have to do it on two levels. In index you have to fetch orders for the current users so users can only see his orders. the second level is you make sure that the user may enter an order url that doesnt belong to him, so check for that in the other actions(edit,update,delete,show).
Or you can use declarative authorization gem. it is very helpful https://github.com/stffn/declarative_authorization
-hint: for naming conventions change belongs_to :users in order model to belongs_to :user (belongs_to is always singular)
This is how your controller should look like
#this is the filter called before each method to make sure the user is authorized to access the order
before_filter :authorize_user, :only => [:edit,:update,:delete,:show]
def index
authorize! :index, #user, :message => 'Not authorized as an administrator.'
#here fetch the orders of the current user only
#orders = current_user.orders
end
#and then goes all your methods here as normal
private
def authorize_user
unless current_user.eql?(#order.user)
flash[:notice]="You are not authorized to access this order"
redirect_to orders_path
end
end