I am newbie to rails using ruby
1.9.3 and rails
4.0.2 and pundit
0.2.1
The post model consists of:
belongs_to :user
The user model is generated by using devise
gem (and does not have has_many :posts
)
devise :database_authenticatable, :registerable,
:rememberable, :trackable, :validatable
I did rake db:drop db:create db:migrate
and my schema.rb
now has user_id
in posts
table.
Then I followed this blog for using gem pundit
I have exactly the same code shown in that blog. Furthermore I added this to my post controller actions:
def create
@post = Post.new(params[:post].permit(:title, :text))
authorize @post
if @post.save
redirect_to @post
else
render 'new'
end
end
def edit
@post = Post.find(params[:id])
authorize @post
end
def update
@post = Post.find(params[:id])
authorize @post
if @post.update(params[:post].permit(:title, :text))
redirect_to @post
else
render 'edit'
end
end
def destroy
@post = Post.find(params[:id])
authorize @post
@post.destroy
redirect_to posts_path
end
I am not getting any kind of error(NoMethodError
like I got when I used cancan
gem).
But no user, not even the author of post, is able to edit and destroy his post.
It simply shows Couldn't find post
. (which is alert message from rescue_from
Pundit::NotAuthorizedError
)
I tried changing logic in PostPolicy
owned
method which is there in blog post but it didn't work.
With these models and schema, how can I achieve this simple authorization (only author of post should be able to edit and delete his post) without using any gems?
I tried other similar questions over here but none worked for me.
As my authorization is working, now i am struggling customising views
specifically edit
and destroy
links for posts index.html.erb
Only Author of a post must be shown edit and delete links for his posts.
I followed elabs/pundit for customising views by using policy method.
Here is my code for post_policy.rb
class PostPolicy < Struct.new(:user, :post)
def owned
post.user_id == user.id
end
def create?
post.user_id = user.id
new?
end
def new?
true
end
def update?
edit?
end
def edit?
owned
end
def destroy?
owned
end
end
And this is the code in post index.html.erb
<% if policy(Post).edit? %>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<% end %>
<% if policy(Post).destroy? %>
<td><%= link_to 'Destroy', post_path(post), method: :delete, data: { confirm: 'Are you sure?' } %></td>
<% end %>
According to pundit documentation on elabs/pundit it says we can get instance of the policy
through the policy
method in both the view
and controller
.
For me it gives NoMethodError in Posts#index
and undefined method user_id for <Class:0x22d64d8>
I have user_id field in post. I think i need to pass @post with policy for getting that user_id. I tried other ways but no success.