3

I have created a message posting feature using ruby the problem I now have is the function editing the post is available but it is accessible by ever single user no matter who posted the original post. How can I make it so the edit 'link' is only viewable or accessible or usable by the original poster. If any code is required please ask, thanks.

This is the error I get now:

undefined local variable or method `current_user' for #<ActionView::Base:0x4cdbb48>
Extracted source (around line #7):

4:     <dd>
5:     <%= car.name %><br />
6:     <%= car.description %><br />
7:     <%= link_to('edit', edit_post_path(@car)) if current_user.cars.include?(@car) %>
8:     <%= link_to "Delete", 
9:     :controller => :car, 
10:    :action => :delete,
Jatinder Singh
  • 307
  • 6
  • 11
  • 19

2 Answers2

2

You need to have the post linked to the creating user in your model, and to check ownership and/or permission in the edit action.

It might be good to use the cancan gem for handling the permission, and to look at this railscast on using it to do a very similar protection to your need.

The railscast uses cancan with authlogic, but it can work with other authentication as well.

Don Roby
  • 40,677
  • 6
  • 91
  • 113
2

If you have a way of getting at the user object, you should have relationships to your posts like this:

class User < ActiveRecord::Base
  has_many :posts
end

class Post < ActiveRecord::Base
  belongs_to :user
end

This lets you get and build posts scoped to the user like so:

User.find(1).posts #=> [<Post id:1>, <Post id:2>, <Post id:4>]

Enumerable#detect can loop over an array and return the first item that evalutates to true in a block like so:

@post = User.find(1).posts.detect do |post|
  post.id == 4
end
@post #=> <Post id:4>

Most Rails apps have some kind of helper to access the currently logged-in user. If not I suggest you put one in application_controller like this:

def current_user
  @current_user ||= User.find(whatever_you_do_to_get_the_logged_in_user)
end

Scope the find in edit and update actions to posts the user owns like this:

def edit
  @post = current_user.posts.detect{|p| p.id == params[:id] }
end

and in your view:

<%= link_to('edit', edit_post_path(@post)) if current_user.posts.include?(@post) %>
Unixmonkey
  • 18,485
  • 7
  • 55
  • 78
  • I am going to give this a go now and see what happens @unixmonkey – Jatinder Singh May 18 '11 at 12:09
  • what is p and p.id? also my post is called 'car' do i not have to define user id to each 'car' that is posted? @unixmonkey – Jatinder Singh May 18 '11 at 12:21
  • I have added the line of code etc should i change p.id to car.id because I have that as the id for each individual post and also how will i define the variable current_user in my car_controller.rb? Please view the error that I now get in the OP – Jatinder Singh May 18 '11 at 12:29
  • p is a temporary variable to check each post against. when the block passed to select evaluates to true, then @post will be the post with the same id as params[:id]. current_user is a kind of de-facto standard in authenticated rails apps if you are using restful_authentication, authlogic, or devise. It is also assumed, you have a relationship for users to posts. Editing a little bit to expand. – Unixmonkey May 18 '11 at 17:47