Rails calling User record from Friends model - ruby-on-rails-3

I've built a simple Friend model, which allows Users to have multiple friends. Here's what that looks like:
class Friend < ActiveRecord::Base
belongs_to :user
class User < ActiveRecord::Base
has_many :friends
Each friend record just has an id, user_id and friend_id. The user_id is the id of the user it belongs to and the friend_id is the id of user they are befriending.
Here's my problem
I'm not quite sure how to display a list of a particular user's friends. #user.friends will give me a list of all the friend records they have, but not the user accounts of those friends.
For instance, I am trying to build a show page for the friends controller:
class FriendsController < ApplicationController
def show
#user = current_user
end
SHOW.HTML.ERB
<% if #user.friends.count > 0 %>
<% #user.friends.each do |friend| %>
<div class="entry">
<%= friend.username %>
This does not work because friend in this case does not have username. I need to do something like this in my controller:
#friend = User.find_by_id(friend.friend_id)
But I'm not sure how I would call that in my view in the #user.friends loop. Any thoughts appreciated. Let me know if I need to be more clear.
UPDATE
I've updated my User model like so:
has_many :friends, :include => :user
has_many :friended_users, :through => :friends, :source => :user, :uniq => true
However, when I run #user.friended_users it's giving me the user_ids (which is the same as #user) rather than friend_ids.
How can I tweak that relationship so it's linking to the friend_id rather than user_id?
The more I think about it, I think I may not have set up the relationship properly in the first place. Maybe a User should has_many :users, through => 'friends', but that doesn't really make sense...
UPDATE
I've updated my models based on #twooface's input:
class User < ActiveRecord::Base
has_many :friendships
has_many :friends, :through => :friendships
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, :class_name => 'User'
class Friend < ActiveRecord::Base
has_many :friendships
has_many :users
I'm just not sure what my Friends table should look like. I assume it should have a primary key and a user_id? If I create a friendship and friend record, I can do friendship.user and friendship.friend and get the correct results, but user.friends gives me an empty hash...

I think your relations are built a bit wrong. Try something like this:
class User < ActiveRecord::Base
has_many :friends
has_many :friendships
has_many :friends, :through => :friendships
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, :class_name => 'User'
# This class has :user_id and :friend_id
Then everything will be simpler. Every user will have an array of friends that will be just users.
User.first.friends
Will return an array of Users that this User friends.
Hope this helps.

Related

How to get single attribute from array in a has_many :through association (User/Friend model)

In my User model I have the following:
class User < ActiveRecord::Base
has_many :friendships, dependent: :destroy
has_many :friends, :class_name => "User", :foreign_key => "friend_id"
has_many :pending_friends,
:through => :friendships,
:conditions => "status = 'pending'",
:foreign_key => "user_id",
:source => :friend
has_many :requested_friends,
:through => :friendships,
:source => :friend,
:conditions => "status = 'requested'"
def friends
direct_friends | inverse_friends
end
In my Friendship model I have the following:
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, :class_name => "User", :foreign_key => "friend_id"
In my view I have created an array of each of the users' friends, shown below. This code works and populates the array with all the data from the friends' "User" database model attributes.
User.first.friends
However, I want to be able to call the users' friend's name's. So, for example, shouldn't I be able to do something like this?
User.first.friends.map(&:name)
How do I get an array containing just the friend's name's, instead of all the friend's user attributes? I would also appreciate if anyone could tell me why .first is used (I got that from here: Rails calling User record from Friends model), as it doesn't just get the first instance of the User's friends (it gets all the instances). And why does just doing:
User.friends
return an empty array?
Try method pluck:
User.first.friends.pluck(:name)
You should use first method to retrieve one object from table. The User is table with a lot of users.

has_many :through causes error: HasManyThroughSourceAssociationMacroError

I need to assign students (users) to classes (studentclasses)
I have a simple many-to-many relationship using 3 tables:
studentclasses (lesson details)
users (user... student info)
studentclass_users (Join table containing user_id and studentclass_id)
I'm using has_many :through and my models look like the following:
studentclass.rb
class Studentclass < ActiveRecord::Base
has_many :studentclass_users
has_many :users, :through => :studentclass_users
end
user.rb
class User < ActiveRecord::Base
...more here...
has_many :studentclass_users
has_many :studentclasses, :through => :studentclass_users
end
studentclass_users.rb
class StudentclassUsers < ActiveRecord::Base
belongs_to :studentclass
belongs_to :user
end
For testing purposes, I'm just using a hidden field in my studentclass new view partial to tack on a user id when creating the class and it is as follows:
_new.html.erb
<%= hidden_field_tag "studentclass[user_ids][]", 29%>
And in my studentclass controller:
studentclasses_controller.rb
def new
#studentclass = Studentclass.new
end
def create
#studentclass = Studentclass.new(params[:studentclass])
#studentclass.save!
end
My params comes back:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"MjBTf4rtcyo8inADrSxPZB3vLOKtlZRVFlQJJzfCqWs=", "studentclass"=>{"class_title"=>"hjhkj", "user_ids"=>["29"]}, "commit"=>"Save"}
which seems fine but I get the following error:
NameError (uninitialized constant ActiveRecord::HasManyThroughSourceAssociationMacroError):
I think this is something simple with naming maybe? Any help would be appreciated

What's the rails way to include a field in a join model when listing an association?

So if I have the following relationship
class Item < ActiveRecord::Base
has_many :item_user_relationships
has_many :users, :through => :item_user_relationships
end
class User < ActiveRecord::Base
has_many :item_user_relationships
has_many :items, :through => :item_user_relationships
end
class ItemUserRelationship < ActiveRecord::Base
belongs_to :item
belongs_to :user
attr_accessible :role
end
What's the rails way to include the role attribute when listing all the Users of an Item?
#users = #item.users # I want to include the role as part of a user
Thanks!
UPDATE: I'm still having trouble with this. My goal is to get an array of User models that have their role included in the attributes.
I'm note sure if I understand you correctly, but maybe this is what you want?
#users = #item.users
#users.each do |user|
puts user.item_user_relationships.first.role
end

Find rows with same some_attribute but two different values for user_id

These are my classes & relations
class User
has_many :conversation_participants
has_many :conversations, :through => :conversation_participants
end
class ConversationParticipant
belongs_to :user
belongs_to :conversation
end
class Conversation
has_many :messages
has_many :conversation_participants
has_many :users, :through => :conversation_participants
end
So when I want to create a conversation between user_ids 12 and 15, I first want to check if a conversation between these two already exists. So what I need to find is this:
ConversationParticipants where user_id IN (12, 15) AND "both conversationparticipant rows have the same conversation id"
I lack the proper words to explain this query but I think everyone will get what I mean. "Does a conversation between these two users exist already?". I know neither how to do it in SQL nor Rails so any answer is appreciated.
EDIT
The id of the conversation would not be known. I need to find if a conversation between those two user_ids exist.
Thanks
-- Emil
class User
has_many :conversations
has_many :conversation_participants
has_many :joined_conversations, :through => :conversation_participants, :source => :conversation
end
class ConversationParticipant
belongs_to :user
belongs_to :conversation
end
class Conversation
belongs_to :user
has_many :conversation_participants
has_many :speakers, :through => :conversation_participants, :source => :user
end
You can try this
#result = ConversationParticipants.where("user_id in ? AND conversation_id=?",[1,2,3,4],2)

How to find all that has multiple relationships in many to many with Rails3 in a elegant way?

I have a User class with
class User < ActiveRecord::Base
has_many :forum_subscriptions
has_many :forums, :through => :forum_subscriptions
And a Forum class with
class Forum < ActiveRecord::Base
has_many :users
I want to find all the users that are subscribed to forum "sport", forum "TV" and forum "Hobby"
What is the most elegant way to do it?
(I have a lot of ugly stuff in my mind :-)
Here is something I would use:
User.joins(:forums).where("forums.title IN (?)", %w(sport TV Hobby)).group("users.id")
I assumed the column for the forum's title is 'title'. Change it when you're using some other name. You can put this inside a nice scope inside the User Model to make it a bit more dynamic.
scope :subscribed_to, lambda { |forum_titles| joins(:forums).where("forums.title IN (?)", forum_titles).group("users.id") }
Now you can call this scope from inside the Controller or some other place:
User.subscribed_to(%w(sport TV Hobby)) # => Get all users that are subscribed to sport, TV and Hobby
User.subscribed_to(["sport", "TV", "Hobby"]) # => Does the same
User.subscribed_to(%w(Hobby)) # => Get all users that are subscribed to Hobby
User.subscribed_to("Hobby") # => Does the same
I assumed you have the following relationships:
class User < ActiveRecord::Base
has_many :forum_subscriptions
has_many :forums, :through => :forum_subscriptions
end
class Forum < ActiveRecord::Base
has_many :forum_subscriptions
has_many :users, :through => :forum_subscriptions
end
class ForumSubscription < ActiveRecord::Base
belongs_to :user
belongs_to :forum
end
Hope this is what you needed. :)