Checking current_user is a post's author - ruby-on-rails

I'm trying to limit editing capability to an article's author in my rails app.
In my controller I'm adding the user id as the author which works fine:
def create
#article = Article.new(article_params)
#article.author = current_user.id
...
end
then checking it on the edit action:
def edit
#article = Article.find(params[:id])
redirect_to root_path, notice: 'Whoa there amigo!' unless current_user.id == #article.author
end
Editing results in redirect every time.
(I'm not using Devise, CanCan or anything else at this point as this is the only functionality I need right now.)
Update
Based on comments, I updated my create method to:
def create
#article = current_user.articles.build(article_params)
and my edit method to:
def edit
#article = current_user.articles.find(params[:id])
redirect_to root_path, notice: 'Whoa..' unless current_user.id.to_s == #article.user_id
This works but "current_user.id.to_s" seems a bit hacky for something that must be incredibly common.

In create action:
def create
#article = Article.new(article_params)
#article.author = current_user
...
end
And in edit change the condition to:
unless current_user == #article.author
This way you compare user objects and not user objects with ids.

Related

value always the same, different in database Rails

This is my ArticleController
def new
#article = Article.new
end
def create
#render plain: params[:article].inspect
#article = Article.new(super_params)
if #article.save
flash[:notice] = "Article has been created"
redirect_to article_path(#article)
else
render 'new'
end
end
def super_params
params.require(:article).permit(:title, :description)
end
def show
#article = Article.find_by( params[:id] )
end
The main problem is that whenever i do: articles/2 or 5 or 6 i get the same article which was created as first. In database records are good i have only this problem with render it.
I know, i did:
find_by
Instead of
find
Sory for trouble...

ForbiddenAttributesError with Active Admin

I 've just started working on ROR.
I made blog app following strictly ROR official doc.
It worked fine for CRDU.
Now I added Active Admin to it, it works fine on delete but gives error while creatiing/updating focusing on
raise ActiveModel::ForbiddenAttributesError
def sanitize_for_mass_assignment(attributes)
if attributes.respond_to?(:permitted?) && !attributes.permitted?
**raise ActiveModel::ForbiddenAttributesError**
else
attributes
end
In Controller, I'm using following code:
def create
#article = Article.new(article_params)
if #article.save
redirect_to #article
else
render 'new'
end
end
def update
#article = Article.find(params[:id])
if #article.update(article_params)
redirect_to #article
else
render 'edit'
end
end
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
private
def article_params
params.require(:article).permit(:title, :text, :AuthorAge)
end
I think you didn't add permit_params in your active admin file.
# app/admin/xyz.rb
permit_params :comma separated attributes.
Look into this link for more detail.

Rails - embedded if statement, unexpected result

I'm getting an unexpected result from an if statement in my Article controller. My intention is to allow the article author or an admin user (it's a boolean column in the users table) to update an article. I want to check if the current user was the original author, and if so, update the author name, just in case the person has changed their username after the article was posted.
The problem is that when an admin updates the article, its not only changing the author name to admin, its also setting the user_id to admin! I don't understand why. The admin.id does not match the article.user_id, so why is this happening?
Here's the bit from the article controller:
def update
#article = Article.find(params[:id])
if #article.user_id == current_user.id || current_user.admin?
#update author in case of user name change
if #article.user_id = current_user.id
#article.author = current_user.name
end
if #article.update(article_params)
redirect_to #article
else
render 'edit'
end
elsif
redirect_to articles_path, :notice => "You do not have permission to edit this resource."
end
end
if #article.user_id = current_user.id
this is an assignment (and always true)
it needs to be if #article.user_id == current_user.id

how to only edit and destroy my own content only?

Have a basic blog (it's actually edgeguide's blog: http://edgeguides.rubyonrails.org/getting_started.html)
Then I integrated Devise into it. So, user can only log in and see their own information.
Now trying to change it somewhat.
I'd like the users to see all content, but only edit and destroy their own only.
Trying to use before_action filter like this:
`before_action :authorize, :only => [:edit, :destroy]`
And this is the authorize method that I wrote:
def authorize
#article = Article.find(params[:id])
if !#article.user_id = current_user.id then
flash[:notice] = "You are not the creator of this article, therefore you're not permitted to edit or destroy this article"
end
end
But it doesn't work. Everything acts as normal, and I can delete mine and everyone's else content.
How do I get it that I can destroy ONLY my own content, and not everyone's else?
Not using CanCan, nor do I want to.
Not sure if this is worth including or not, but originally when I had everyone see their own content, that was via create action:
def create
#article = Article.new(article_params)
#article.user_id = current_user.id if current_user
if #article.save
redirect_to #article
else
render 'new'
end
end
You're having several problems
first, look at that :
if !#article.user_id = current_user.id then
You're only using one = instead of == so you are doing an assignation that will evaluate to current_user.id
Also, in your condition, you're only setting a flash message but not doing anything to really prevent the user.
Here's a corrected version :
def authorize
#article = Article.find(params[:id])
unless #article.user_id == current_user.id
flash[:notice] = "You are not the creator of this article, therefore you're not permitted to edit or destroy this article"
redirect_to root_path # or anything you prefer
return false # Important to let rails know that the controller should not be executed
end
end

Updating a record via a action method

User signs up, is redirected to a page to be collected info, pretty straight forward
I for my life can't figure out how to do this
My controller for the user
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def additional_info
#user = User.find session[:user_id]
#user = User.update(user_addinfo)
redirect_to user_path
end
def create
#user = User.new(user_params)
if #user.save
#session[:user_id] = #user.id
#UserMailer.welcome_email(#user).deliver
sign_in #user
redirect_to additional_info_path
flash[:success] = "Welcome to InYourShoes!"
else
render'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
def user_addinfo
params.require(:user).permit(:year)
end
end
user_addinfo is the action method that i want to call updating my record on for my additional_info method.
the def create method has commented line that i'm unsure if necessary, particularly the session[:user_id] = #user.id. I was told that i need this in order to keep track of my session, but perhaps someone can debunk this for me, as im following michael hartl's tutorial.
as of right now with this code, rails is giving me a parameter missing in the
params.require(:user).permit(:year) line.
Much help is greatly appreciated. Ive been trying many different things, and cant seem to figure this out
Change your controller code as below:
def additional_info
#user = User.find params[:id] ## Set #user
end
def update
if #user.update(user_addinfo)
redirect_to user_path(#user), notice: 'User was successfully updated.'
else
render action: 'additional_info'
end
end
def create
#user = User.new(user_params)
if #user.save
#session[:user_id] = #user.id
#UserMailer.welcome_email(#user).deliver
sign_in #user
redirect_to additional_info_path(#user) ## Pass #user
flash[:success] = "Welcome to InYourShoes!"
else
render'new'
end
end
and in your routes.rb update the additional_info route as
get 'info/:id' => 'users#additional_info', :as => 'additional_info'
You additional_info action seems to be wrong. You need to pass in the id of the user for whom you are collecting additional information.
def additional_info
#user = User.find params[:id]
#user.update_attributes(user_addinfo)
redirect_to user_path(#user)
end
The line you have commented in your create method:
#session[:user_id] = #user.id
Is what is storing the user id to a session variable and not a param in the url.
You then have this line commented in your additional_info method
#user = User.find session[:user_id]
This is looking up the user by the id that you would have previously stored in the session variable.
At that point the user object would be stored in user
If you need it in your instance variable, make sure to modify the line to be
#user = User.find session[:user_id]
Your user would then be stored in #user and be able to be accessed in the view

Resources