0

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.

Swapnil Sawant
  • 620
  • 8
  • 21
  • 1
    It would be useful to see your application controller code and your post policy. Also, your controller here doesn't show how you're assigning the post to the user when it's created so check your database and see if any of the posts you have created have a user_id assigned to them. This may well be your problem. – Andy Henson Mar 26 '14 at 13:44

1 Answers1

0

Thanks Uri for editing the question.

Thanks a ton Andy for guiding me properly. As you said the user_id was nil for new post created. I just assigned current user's id to post.user_id in create method

def create?
 post.user_id = user.id
 new?
end

in

post_policy.rb

All my auhtorizations are now working fine.

But now I am struggling with policy method used for customising views. I have edited the question accordingly along with code.

Swapnil Sawant
  • 620
  • 8
  • 21