0

I have been practicing working on this rails application where I want to allow registered users to put up profiles of their dogs. But I just can't get the My Dogs page to display dogs that belong only to the current logged in user.

I already have the dog and user models linked via Active Record (User has_many :dogs, Dog belongs_to :user) but I don't know what to type in my dogmenu view to display only dogs that belong to the current logged in user. This is what I have so far:

views\access\dogmenu.html.erb <-- Notice that the page that will display the dogs for the current logged in user is located in the view of another controller.

<div id="dogdisplay">
  <table>
<tr>
  <th>Dog Name</th>
  <th>Breed</th>
</tr>
<% Dog.all.each do |d| %>
<tr>
  <td><%= link_to d.dname, d %></td>
  <td><%= d.breed %></td>
  <td><%= link_to "Edit", edit_dog_path(d) %></td>
  <td><%= link_to "Delete", d, method: :delete %></td>
</tr>
<% end %>
</table>
</div>

Thank you.

Zero
  • 151
  • 10

4 Answers4

2

You will need two things to make this work:

  1. A User object for the logged in user
  2. Filter the dog list based on that id

1. Current User

This is pretty straightforward, you should be able to find this with a little googling. The big question is whether you've implemented your own user management, or you're using something like Devise to manage that.

If it's Devise, take a look at Rails Devise: get object of the currently logged in user?

If you wrote your own, you could take a look at how Devise or other user management gems provide access to the current user object. I'll leave that up to you because it seems beyond the scope of your question

2. Filter the dog list

This is pretty simple, you've got a few options:

From the view

current_user.dogs.each do |d|

Dog.where(user: current_user).each do |d|

Dog.where(user_id: current_user.id).each do |d|

From the controller

What @Sean Huber suggested is cleaner - use any of my methods above, but from the controller. E.g.

@dogs = current_user.dogs

In short, only take the dogs that have the user id matching the current user's.

Community
  • 1
  • 1
alexanderbird
  • 3,847
  • 1
  • 26
  • 35
1

I would suggest you set an instance variable in your controller action for the current user's dogs. Something like this:

def dogmenu
  # this assumes you have a current_user already defined
  @dogs = current_user.dogs
end

Then switch your view to use the instance variable @dogs:

<div id="dogdisplay">
  <table>
<tr>
  <th>Dog Name</th>
  <th>Breed</th>
</tr>
<% @dogs.each do |d| %>
<tr>
  <td><%= link_to d.dname, d %></td>
  <td><%= d.breed %></td>
  <td><%= link_to "Edit", edit_dog_path(d) %></td>
  <td><%= link_to "Delete", d, method: :delete %></td>
</tr>
<% end %>
</table>
</div>
Sean Huber
  • 3,945
  • 2
  • 26
  • 31
  • This definitely do the job. Once again I can't believe the answer was so simple, and here I was even thinking on making the dogmenu inside the Users view because I kept on getting Undefined method errors with what I was trying to do. Thanks again!. – Zero Oct 13 '15 at 03:25
  • 1
    Glad it worked! It is always good practice to keep method calls that invoke database queries (like `Dog.all`) in your controllers instead of in your views. Cheers. – Sean Huber Oct 13 '15 at 03:29
0

To get current user dogs, you can use object current_user Change this Controller

def dogmenu
  @dogs = current_user.dogs
end

View

<% @dogs.each do |d| %>

To make current_user can execute in view put a helper method.

class ApplicationController < ActionController::Base
  helper_method :current_user

  def current_user
    @current_user ||= User.find_by_id(session[:user])
  end
end

Finally you can use current_user in your view or helper

<% current_user.dogs.each do |d| %>
<tr>
  <td><%= link_to d.dname, d %></td>
  <td><%= d.breed %></td>
  <td><%= link_to "Edit", edit_dog_path(d) %></td>
  <td><%= link_to "Delete", d, method: :delete %></td>
</tr>
<% end %>

It's good for trying the first one where you're using instance variable. Hopefully it can help.

akbarbin
  • 4,985
  • 1
  • 28
  • 31
  • Thank you, but for some reason calling the current_user variable just like that did not work even when i have current_user defined in my application_controller.rb. – Zero Oct 13 '15 at 03:24
  • It's okay. I will update it and put it into controller – akbarbin Oct 13 '15 at 03:26
0

You need to retrieve the dogs related to the current user. Since these are the user's dogs, the logic should reside in the UsersController:

In _controller/users_controller.rb_

def your_method_name
    @user = User.find(current_user.id)
    @dogs = @user.dogs
   render :dogmenu
end

Then in views/users/dogmenu.html.erb

<div id="dogdisplay">
  <table>
<tr>
  <th>Dog Name</th>
  <th>Breed</th>
</tr>
<% @dogs.each do |d| %>
<tr>
  <td><%= link_to d.dname, d %></td>
  <td><%= d.breed %></td>
  <td><%= link_to "Edit", edit_dog_path(d) %></td>
  <td><%= link_to "Delete", d, method: :delete %></td>
</tr>
<% end %>
</table>
</div>

These are user dogs so the view really belongs in the users folder.

Cyzanfar
  • 6,997
  • 9
  • 43
  • 81