RoR has_two relation: a Donation between two Users - ruby-on-rails

I have a problem I find difficult to search the web for an answer...
I have in my Ruby On Rails two models: User and Donation.
I want that a Relation has two user: user1 gives 10$ to user2.
This is what I came with:
class Donation < ActiveRecord::Base
attr_accessible :description, :value, :from_user_id, :to_user_id
def from_user
User.find(from_user_id)
end
def to_user
User.find(to_user_id)
end
end
But I would like to use relationships... Do you know the best way of doing this?
Thanks a lot :)

has_one :from_user, :class_name => 'User', :foreign_key => 'from_user_id'
has_one :to_user, :class_name => 'User', :foreign_key => 'to_user_id'
Relations are nothing special... well, okay, they are now, but this essentially constructs the appropriate sql. I think. Haven't tried it.

Related

What's the most idiomatic way to model this relationship in Rails?

Let's say we have coaches, clients, and users.
What's the ideal way to model this in a way that isn't inheritance? I'd like to avoid STI.
Right now I have something like this:
user.rb
has_many :coaches, :foreign_key => :client_id
has_many :coach_users, :through => :coaches, :source => :user
has_many :clients, :class_name => "Coach"
has_many :client_users, :through => :clients, :source => :client
def is_a_coach_of?(client)
self.client_users.include?(client)
end
def is_a_client_of?(coach)
self.coach_users.include?(coach)
end
coach.rb
belongs_to :user
belongs_to :client, :class_name => "User"
But this feels really clunky to deal with a User object that is supposedly a 'coach' and having to type user.coach_users to get a collection of users that are being coached by this specific user.
It feels very non idiomatic and quite honestly, it's just plain confusing and I hate it. I want something more elegant.
I thought of removing the join model and just having two has_many's on the user.rb model but it still feels clunky, especially the icky feeling of violating roles of objects. These are different roles but are also very similar because they're all a user. How do you separate such common logic in an elegant way, in the right idiomatic way with Rails and Ruby?
A "user of the site" can exist without being a coach or a client.
If the modeling requires just a relationship, then I can see it be a HABTM but what if the individual relationship requires extra logic? E.g extra logic on client or coach? Would you just mixin a class that defines logic in the User model? Or would you create separate AR models for the relationship and if so, how?
If a client/coach is just a relationship, it can be just that, not a separate model. So you can do a has_and_belongs_to_many relationship between Users. Create a migration with:
def up
create_table :coaches_clients do |t|
t.integer :coach_id
t.integer :client_id
end
end
and in you model:
has_and_belongs_to_many :clients,
:foreign_key => 'client_id',
:association_foreign_key => 'coach_id',
:class_name => 'User',
:join_table => 'coaches_clients'
has_and_belongs_to_many :coaches,
:foreign_key => 'coach_id',
:association_foreign_key => 'client_id',
:class_name => 'User',
:join_table => 'coaches_clients'

Mongoid self reference with properties for users friendships status

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

Rails How to get all the grandchildren of an ojbect

I have 3 models:
User
has_many :questions
has_many :corrections
end
Question
has_one :correction
belongs_to :user
end
Correction
belongs_to :user
belongs_to :question
So if user Bob asks a question then user Terry can check it and if its wrong offer a correction.
Lets stay with bob and assume he as kindly corrected 5 other users, i.e and lets assume he has been lucky to get 3 corrections from other users.
I want to be able to do something like this
#bob.corrections_offered => 5 correction objects
#bob.corrections_received => 3 correction objects
the first one is easy as its really just #bob.corrections under the hood. But I dont know how to implement the latter one. Can anyone help?
UPDATE
So I tried using through as suggested like so (Oh and actually the question model above is actually called Sentence in my code. I.e. User => Sentence => Correction. )
has_many :sentences
has_many :corrections_received, :through => :sentences, :class_name => 'Correction'
but got this error in console
ActiveRecord::HasManyThroughSourceAssociationNotFoundError:
Could not find the source
association(s) :Correction in model
Sentence. Try 'has_many
:corrections_received, :through =>
:sentences, :source => '. Is it
one of :language, :correction, :user,
or :checker?
So tried the following
has_many :corrections_received, :through => :sentences, :source => :correction
but got
ActiveRecord::HasManyThroughSourceAssociationMacroError:
Invalid source reflection macro
:has_one for has_many
:corrections_received, :through =>
:sentences. Use :source to specify
the source reflection.
not sure whats going wrong...
You can add a has_many through relationship in your user model like so
class User
#your usual relationships
has_many :corrections_received, :through => :questions, :class_name => 'Correction'
end
Try the following way:
has_many :corrections_received,:class_name=>'Correction',:conditions=>...
Normally, you should be able to do it with :through, but I'm not sure if two user->correction relationships are possible.
In any case, helper method in the model class should be simple enough. Something like this.
def corrections_received
result = Array.new
questions.each do |q|
if q.correction
result.push q.correction
end
end
result
end
Since I'm new to this stuff, corrections are welcome!

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

Graph Edges Rails

I found this recently when trying to do bidirectional relationships in rails
(http://www.dweebd.com/sql/modeling-bidirectional-graph-edges-in-rails/)
class Befriending < ActiveRecord::Base
belongs_to :initiator, :class_name => :User
belongs_to :recipient, :class_name => :User
after_create do |b|
BefriendingEdge.create!(:user => b.initiator, :befriending => b)
BefriendingEdge.create!(:user => b.recipient, :befriending => b)
end
end
class BefriendingEdge < ActiveRecord::Base
belongs_to :user
belongs_to :befriending
end
class User < ActiveRecord::Base
has_many :befriending_edges
has_many :friends, :through => :befriending_edges, :source => :user
has_many :befriendings, :through => :befriending_edges, :source => :befriending
end
But I just don't quite understand how it works. Can anyone helps explain to me. It looks like a double belongs_to. Just not quite understanding this.
Thanks
I'm a user
I have friends
My friends are also users
The way to model this using a graph (http://en.wikipedia.org/wiki/Graph_%28mathematics%29) is with
nodes that represent users/friends
edges that represent friendship links
So yes: in databases terms, "users belong to users" : my friends are also users. But in addition, friendship is bi-directional: if we're friends that means, I'm your friend AND you're my friend.
Also, using a separate model to store edges/relationships allows you potentially store additional information about the friendship (e.g. "friends since").

Resources