Mongoid self reference with properties for users friendships status - ruby-on-rails

Using Mongo and Rails, I would to build a friendship system like facebook:
- Before making the friendship, the use must accept the friendship request
I found a lots of code to do the relationship but never with a relation's property...
Do you have any idea or clue how to do that to be "respectful" of the NoSQL concept
Thank you for your help

Just use two models, something like this:
class User
include Mongoid::Document
has_many :friendships
end
class Friendship
include Mongoid::Document
belongs_to :owner, :class_name => "User"
belongs_to :friend, :class_name => "User"
field :pending, :type => Boolean, :default => true
end
Does it sound good? Hope this helps!

I had to put in my User model:
has_many :friendships, :inverse_of => :owner
Check out associations in the documentation http://mongoid.org/en/mongoid/docs/relations.html#common

Related

Rails many to many relationship confusion

So im working on a rails app for users to create events (and attend other created events). You can read about the assignment here (for the Odin Project): https://www.theodinproject.com/courses/ruby-on-rails/lessons/associations
Anyways I thought I had understood many to many relationships in rails, but the way i've seen other people write the models is confusing to me.
To me it seems like it should be something like:
class User < ApplicationRecord
has_many :attendances
has_many :events, through: :attendances
end
class Attendance < ApplicationRecord
belongs_to :user
belongs_to :event
end
class Event < ApplicationRecord
has_many :users
has_many :users, through: :attendances
end
This makes sense to me because a User can create many events, and an event can have many users attending. (Although attendances is probably the wrong word, maybe invites or something).
But i've seen some weird examples (You can see others source code below on the project) and it seems like they are adding much more to the models and also renaming the source/foreign_key/class_name.
Am I missing something? This still allows a user to "own" an event right? Maybe im mis-understanding how many-to-many works. But this fits at least in my mind of how it should be.
For reference some other models I was seeing was similar to this:
class Event < ActiveRecord::Base
belongs_to :creator, :class_name => "User"
has_many :event_attendees, :foreign_key => :attended_event_id
has_many :attendees, :through => :event_attendees
end
class EventAttendee < ActiveRecord::Base
belongs_to :attendee, :class_name => "User"
belongs_to :attended_event, :class_name => "Event"
end
class User < ActiveRecord::Base
has_many :created_events, :foreign_key => :creator_id, :class_name => "Event"
has_many :event_attendees, :foreign_key => :attendee_id
has_many :attended_events, :through => :event_attendees, :foreign_key => :attendee_id'
end
Basically similar things to the above. Im not really sure what this is doing? Or why all the extra is necessary.
In your example everything according to conventions. Maybe except many-to-many table naming.
attendances table has 'user_id' and 'event_id' fields. But in case it could conflict with other fields, or not descriptive enough you could use different keys.
belongs_to :creator, :class_name => "User"
belongs_to :creator by default would look for Creator model, so it is needed to specify class name explicitly, like in the provided example.
has_many :event_attendees, :foreign_key => :attended_event_id
By default foreign key would be event_id, so here it is specified explicitly too.
has_many :created_events, :foreign_key => :creator_id, :class_name => "Event"
By default, rails would look for user_id foreign key and CreatedEvent model. And these attributes specified explicitly.
You just need to understand what attributes rails provides by default, to change if it is required.
ActiveRecord associations default to a class and foreign key with the same name as the association. The code here is specifically specifying these because they are not the default.

how to setup two user_id columns in one model in rails?

I have two models
class User
has_many :disputes
end
class Dispute
belongs_to :user
end
So Dispute has :user_id, but my problem is that a Dispute has 2 sides - the claimant and the indicted, both of which are users.
I tried to solve this problem by creating two columns: :claimant_id and :indicted_id, and passing arguments like #dispute.claimant_id = current_user.id, but after that I can't use a relationship tricks like #dispute.user.name or #user.disputes with my :claimant_id and :indicted_id.
Is there any way to set up two :user_id (like a claimant and an indicted) in one model and still maintain the relationships between Dispute and User models?
You can go the route of having :claimant_id and :indicted_id on your users table, but in your class def you need
class Dispute < ActiveRecord::Base
belongs_to :claimant, class_name: 'User', :foreign_key => :claimant_id
belongs_to :indicted, class_name: 'User', :foreign_key => :indicted_id
end
Reference: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-belongs_to
I think this is a duplicate of Ruby on Rails Double Association
For your case use class_name as the second parameter to your belongs_to function and a hash with foreign_key and the id column name (as pointed out by #devkaoru), like so:
class Dispute < ActiveRecord::Base
belongs_to :claimant, class_name: 'User', :foreign_key => :claimant_id
belongs_to :indicted, class_name: 'User', :foreign_key => :indicted_id
end
I think that should do it up right.
Disclaimer: This is an untested solution

Association through non-standard column?

I have a Friends model with user_id and friend_id...both are id's back to specific users.
What I'd like to able to do is something like this:
#relationship = Friend.find_by_user_id(current_user.id)
#relationship.friend.username
Where I can basically pull the user through the friend_id column in the same way I can do #relationship.user.username.
How would I setup my associations to pull that off?
Isn't this just a many-to-many situation.
I think there is a perfect solution in Many-to-many relationship with the same model in rails?
Hope this help!
Use class_name if your column doesn't reflect the convention expected:
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, class_name: 'User'
end
Note that I modified the model name to Friendship to better reflect the use of this model. Also, you can make it easier for yourself if you revise your User model to look like this:
class User < ActiveRecord::Base
has_many :friendships
has_many :friends, :through => :friendships
has_many :friendships_of, :class_name => 'Friendship', :foreign_key => :friend_id
has_many :friends_of, :through => :friendships_of, :source => :user
end
Now to see all the user's friends:
current_user.friends.map(&:username)
And to see who has 'friended' the user:
current_user.friends_of.map(&:username)

When an association is specified with class name, how do you access it? Rails 3

So lets I have a Transactions model.
Transactions.rb has:
belongs_to :buyer, :class_name => "User"
belongs_to :seller, :class_name => "User"
The user logged in, is accessed with current_user.
How can I do something like current_user.transactions? (which won't work as transactions doesn't have a user_id column) Or something like current_user.transactions.buyer?
Thanks!
(also the user model has_many :transactions)
All associations in Rails are one-way.
So for each belongs_to, you need to add a has_many or has_one on the other side.
I'd suggest you want something like this;
class User
has_many :transactions_as_buyer,
:class_name => "Transaction",
:foreign_key => :buyer_id
has_many :transactions_as_seller,
:class_name => "Transaction",
:foreign_key => :seller_id
end
Now you can say;
current_user.transactions_as_seller.map(&:buyer)
to get an array of buyers.
Of course, depending on your app you may have a better name than "transactions_as_buyer/seller"

How can I have two columns in one table point to the same column in another with ActiveRecord?

I run the risk of palm-to-forehead here, but I can't quite figure out how to do this with Rails' ActiveRecord sugar.
I have a tickets table that has two columns (submitter_id and assignee_id) that should each reference a different user from the users table (specifically the id column in the users table). I'd like to be able to do things like ticket.submitter.name and ticket.assignee.email using ActiveRecord's associations. Submitter and Assignee are simply user objects under different associative names.
The only thing I've found that comes close to what I am doing is using polymorphic associations, but in the end I'm fairly certain that it's not really what I need. I'm not going to have multiple types, both submitter and assignee will be users, and very well could be two different users.
Any help would be fantastic. Thanks!
class Ticket < ActiveRecord::Base
belongs_to :submitter, :class_name => "User"
belongs_to :assignee, :class_name => "User"
end
Should work.
Edit: Without trying it out, I'm not sure whether you need the :foreign_key parameter or not. My instinct is not, but it couldn't hurt.
Edit again: Sorry, left off the User -> Ticket associations. You didn't mention using them, and I typically will only add associations in one direction if I don't plan on using them in the other direction.
Anyway, try:
class User < ActiveRecord::Base
has_many :assigned_tickets, :class_name => "Ticket", :foreign_key => "assignee_id"
has_many :submitted_tickets, :class_name => "Ticket", :foreign_key => "submitter_id"
end
Something like this should work
class Ticket < ActiveRecord::Base
belongs_to :submitter, :class_name => 'User', :foreign_key => 'submitter_id'
belongs_to :assignee, :class_name => 'User', :foreign_key => 'assignee_id'
end
class User < ActiveRecord::Base
has_many :tickets, :class_name => 'Ticket', :foreign_key => 'submitter_id'
has_many :tickets_assigned, :class_name => 'Ticket', :foreign_key => 'assignee_id'
end
Yes, PreciousBodilyFluids is right we don't need to specify the foreign_key in the Ticket class as rails can infer it from the column name, i.e. submitter_id and assignee_id
But if your association name is different from the column_name_{id} then you will have to specify it, i.e. the User class case

Resources