Two 1 - N relations in Mongoid (Rails) - ruby-on-rails

The scenario is:
How can an Account give ratings to another account? This results in two lists on the Account. Those who I have rated and those who have rated me. (my_ratings and ratings_given)
This boils down to:
How can multiple 1 - N relationsips to the same entity work in Mongoid?
In Mongoid's Docs it says you can use has_many and belongs_to to link the entities together.
I currently have this on Account
has_many :ratings, :as => "my_ratings"
has_many :ratings, :as => "ratings_given"
and this on Ratings:
belongs_to :user, :as => 'Rater'
belongs_to :user, :as => 'Ratie'
The docs don't cover this case, so I thought you would have to differentiate between the two with an :as parameter.
Is this even remoting correct?

You can achieve what you want using the class_name and inverse_of options:
class Account
include Mongoid::Document
field :name
has_many :ratings_given, :class_name => 'Ratings', :inverse_of => :rater
has_many :my_ratings, :class_name => 'Ratings', :inverse_of => :ratee
end
class Ratings
include Mongoid::Document
field :name
belongs_to :rater, :class_name => 'Account', :inverse_of => :ratings_given
belongs_to :ratee, :class_name => 'Account', :inverse_of => :my_ratings
end
The documentation has changed since I was last working with it so I wasn't sure whether this is still the recommended approach. Looks like it doesn't mention these options on the 1-many referenced page. But if you take a look at the general page on relations they are covered there.
In any case you need to explicitly link ratings_given/rater and my_ratings/ratee associations when there are two associations to the same class, otherwise mongoid has no way to know which of the two potential inverses to pick.

Related

Rails has many through self unique validation

I have two models, Users and Coachings
One user can have many students and coaches
Code from the Users model:
has_many :coachings, :foreign_key => :student_id
has_many :coaches, :through => :coachings, :foreign_key => :coach_id
Code from the Coachings models:
belongs_to :coach, :class_name => 'User'
belongs_to :student, :class_name => 'User'
But this allows to add duplicate records to db (one user can have duplicate coaches or duplicate students). How to properly validate this?
Thanks
It seems like you are looking for a way to validate the uniqueness of the combindation of coach_id and student_id.
Try this:
coaching.rb
validates_uniqueness_of :coach_id, scope: :student_id

Naming polymorphic relationships well

This question is about the naming style of polymorphic relationships.
My database has three types of person: a 'Company', a Client, and an Employee. Each of the three are in polymorphic relationships with tasks and events, and projects.
According to the Rails guides, this would be done like (I've omitted some classes for brevity):
Person.rb
has_many :tasks, :as => :taskable
has_many :events, :as => :eventable
has_many :projects, :as => :projectable # awkward names
Task.rb
belongs_to :taskable, :polymorphic => true
These lead to the rather strange:
#person = #task.taskable
I feel that the following would be far more grammatical and elegant... would it work, and if so, is there a reason that official sources use words like projectable rather than words like owner?
Person.rb
has_many :tasks, :as => :owner
has_many :events, :as => :owner
has_many :projects, :as => :owner
Task.rb
belongs_to :owner, :polymorphic => true
This creates the elegant:
#person_1 = #task.owner
#person_2 = #project.owner
I personally try to keep it as generic as possible.
So :as => :owner does make more sense to me.
In case of doubt, I'd just use
:as => :parent
which I've already seen in some projects.

Accessing two sides of a user-user relationship in rails

Basically, I have a users model in my rails app, and a fanship model, to facilitate the ability for users to become 'fans' of each other.
In my user model, I have:
has_many :fanships
has_many :fanofs, :through => :fanships
In my fanship model, I have:
belongs_to :user
belongs_to :fanof, :class_name => "User", :foreign_key => "fanof_id"
My fanship table basically consists of :id, :user_id and :fanof_id. This all works fine, and I can see what users a specific user is a fan of like:
<% #user.fanofs.each do |fan| %>
#things
<% end %>
My question is, how can I get a list of the users that are a fan of this specific user?
I'd like it if I could just have something like #user.fans, but if that isn't possible what is the most efficient way of going about this?
Thanks!
Add in User model:
has_many :my_fanclubs, :class_name => 'Fanship', :foreign_key => 'fanof_id'
has_many :fans, :through => :my_fanclubs, :source => :user, :class_name => 'User'
(not tested)

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

Going from 2 to many in Rails

I have a Rails application that I'm in the process of designing. I have a separate model that needs to link to only 2 of one model. Specifically, my "evaluation"s have 2 "member"s, an evaluator, and an evaluatee. They also have a few other pieces of information, too but they should not be relevant to this.
What is the best way to represent this? Would 2 foreign keys in the evaluation be best, or a many-many relationship between the evaluations and the members? Would there be some other option that would work even better?
I would initially think many to many, but since there is a defined number on one side of the relationship I question the applicability here. To my knowledge, many-to-many generally implies that the number on each side of the relation is variable.
You probably want two different associations, possibly with the same class:
class Member < ActiveRecord::Base
has_many :evaluations_out, :class_name => 'evaluation', :as => :evaluator
has_many :evaluations_in, :class_name => 'evaluation', :as => :evaluatee
end
class Evaluation < ActiveRecord::Base
belongs_to :evaluator, :class_name => 'member'
belongs_to :evaluatee, :class_name => 'member'
end
I haven't tested it myself and it might sound a little adventurous, but I think that could work:
Evaluation Model
class Evaluation < ActiveRecord::Base
belongs_to :evaluator, :class_name => "Member", :foreign_key => "evaluator_id"
belongs_to :evaluatee, :class_name => "Member", :foreign_key => "evaluatee_id"
end
Member Model
class Member < ActiveRecord::Base
has_many :evaluators, :class_name => "Evaluation", :foreign_key => "evaluator_id"
has_many :evaluatees, :class_name => "Evaluation", :foreign_key => "evaluatee_id"
end

Resources