Self-referencing models in Rails 3 - ruby-on-rails

I have an Entity model and I want to display connections between the Entities. ie, Entity 1 is connected to Entity 2.
My thinking, right now, is to create a join model between the two called Connection and have it work like a traditional rails join table. Except have the columns be entity_one_id and entity_two_id, then establish a many-to-many relationship between Entity and Connection.
This seems like a really not-elegant way to do this. I was wondering if anyone had any better ideas? Maybe something more rails-esque that I'm just not seeing?

That's the most-common way to do it. If an entity is only ever connected to one other model, you could use a linked-list, tree-like structure.
Check out Ryan Bates' Railscast on self-joining models. It deals with a social-network-like system, but it still has principles you'll need and provides a great starting point

You could use this implementation:
class User < ActiveRecord::Base
has_many :friends, :through => :friendships, :conditions => "status = 'accepted'"
has_many :requested_friends, :through => :friendships, :source => :friend, :conditions => "status = 'requested'", :order => :created_at
has_many :pending_friends, :through => :friendships, :source => :friend, :conditions => "status = 'pending'", :order => :created_at
has_many :friendships, :dependent => :destroy
end
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend, :class_name => "User"
end

Related

Rails relationships

How would I define a relationship where an employee has a manager, and potentially some subordinates (all of which would be examples of the Employee model)? My attempt so far results in any given person only having a maximum of one subordinate.
has_one :manager, :class_name => Employee, :foreign_key => "manager"
has_many :subordinates, :class_name => Employee, :foreign_key => "manager"
I feel like this one's obvious, but all the banging of my head against the wall is making it difficult.
Try this one:
class Employee
belongs_to :manager, :class_name => 'Employee', :inverse_of => :subordinates
has_many :subordinates, :class_name => 'Employee', :inverse_of => :manager
end

Rails multiple associations between two models

I have Flight, Person, and Glider models in a Rails 3 app. I've defined custom relationships because I need more than one foreign key referencing a Person from the flights table. Associations work but ONE-WAY only.
class Flight < ActiveRecord::Base
belongs_to :pilot, :class_name => "Person"
belongs_to :instructor, :class_name => "Person"
belongs_to :towplane_pilot, :class_name => "Person"
belongs_to :airplane_instructor, :class_name => "Person"
belongs_to :glider
belongs_to :rep_glider, :class_name => "Glider"
belongs_to :departure_airfield, :class_name => "Airfield"
belongs_to :arrival_airfield, :class_name => "Airfield"
end
class Glider < Aircraft
has_many :flights
has_many :replaced_flights, :foreign_key => "rep_glider_id", :class_name => "Flight"
end
class Person < ActiveRecord::Base
has_many :flights, :foreign_key => "pilot_id", :class_name => "Flight"
has_many :instructed_flights, :foreign_key => "instructor_id", :class_name => "Flight"
has_many :towed_flights, :foreign_key => "towplane_pilot_id", :class_name => "Flight"
has_many :instructed_towing_flights, :foreign_key => "airplane_instructor_id", :class_name => "Flight"
end
####What works#####
Flight.first.glider
Flight.first.rep_glider
Flight.first.pilot
Flight.first.instructor
Flight.first.towplane_pilot
Flight.first.airplane_instructor
Glider.first.flights
Glider.first.replaced_flights
####What doesn't work#### ----> NoMEthodError 'match'
Person.first.flights
Person.first.instructed_flights
Person.first.towed_flights.
Person.first.instructed_towing_flights
I'm almost there, but I don't understand how Glider.first.flights does work when Person.first.flights doesn't.
UPDATE: Associations with 'Airfield' works... so I'm clueless as to why it doesn't work with 'Person'
class Airfield < ActiveRecord::Base
has_many :takeoff_flights, :foreign_key => "departure_airfield_id", :class_name => "Flight"
has_many :grounded_flights, :foreign_key => "arrival_airfield_id", :class_name => "Flight"
end
###Works Correctly
Airfield.first.takeoff_flights
Airfield.first.grounded_flights
Flight.first.departure_airfield
Flight.first.arrival_airfield
Do your pilots have types? like a pilot_type column? I just also started reading into these kinds of patterns and luckily it's still a bit fresh(hopefully. please correct me if Im wron rails ninjas! :))
You are in need of the polymorphic pattern as discussed here:
http://asciicasts.com/episodes/154-polymorphic-association
I've been told that the association between these models is set correctly.
I added a new record to the flights table, and now the associations work correctly with this new record and all the previous ones. I'm not really sure how it is working now, but it sure does.

Rails, has_many polymorphic association to one model

I would like to have one model (event) that has multiple polymorphic HABTM associations to the same user model.
It should work something like this:
Event < ActiveRecord::Base
has_many :admin_users, :through => :event_users, :source => :userable, :source_type => 'User'
has_many :participating_users, :through => :event_users, :source => :userable, :source_type => 'User'
has_many :paid_users, :through => :event_users, :source => :userable, :source_type => 'User'
has_many :done_users, :through => :event_users, :source => :userable, :source_type => 'User'end
class EventUser < ActiveRecord::Base
belongs_to :userable, :polymorphic => true
belongs_to :event
end
User < ActiveRecord::Bas
has_many :event_users, :as => :userable
has_many :events, :through => :event_users
end
This almost works!! The problem is though that userable_type gets the type "User" for all diffrent associations. Is it possible to solve this?
I'm afraid your associations look totally wrong. First of all, if you have a 'has_many' on one side of a association, you have to have a 'belongs_to' on the other side. Secondly, I'm guessing done_user, admin_user etc inherit from User. Am i correct ?
And how different are participating_user, admin_user etc different from each other? Do you really need classes for each of these, can you make do with named scopes?
I would suggest you simplify your data model.
Right now your modeling looks fuzzy. Please do elaborate.
EDIT
Honestly, I think your modeling is over complicated. If I were you, given your descriptions of *_users, I would just have named scopes to retrieve that type of an user. So in effect
class Event < ActiveRecord::Base
has_many :event_users
has_many :users, :through => :event_users
end
class User < ActiveRecord::Base
has_many :event_users
has_many :events, :through => :event_users
end
So now, write named scopes in your User model to retrieve *_user.
Here's an excellent screencast on named_scopes.

Right way to force uniqueness on a join model? (has_many :through)

I have a parent/child relationship via our users table, with models as such:
class User < ActiveRecord::Base
# Parents relationship
has_many :children_parents, :class_name => "ParentsChild", :foreign_key => "child_id", :dependent => :destroy
has_many :parents, :through => :children_parents
# Children relatiopnship
has_many :parents_children, :class_name => "ParentsChild", :foreign_key => "parent_id", :dependent => :destroy
has_many :children, :through => :parents_children
...
end
And in parents_child.rb:
class ParentsChild < ActiveRecord::Base
belongs_to :parent, :class_name => "User"
belongs_to :child, :class_name => "User"
end
Right now, it is possible in our "add children" form (just using vanilla nested attributes) to add the same user as a child multiple times for parents. I am not sure what the 'right' way to go about forcing uniqueness in the ParentsChild relationship, although I am leaning towards a unique index on (parent_id, child_id) at the database layer (using a migration of course).
I am sure I could also enforce uniqueness constraints in the UsersController::update method, but would prefer to avoid changing that code (right now it doesn't reference parents/children at all, thanks to nested attributes in the form/model) if possible. I am most concerned with making sure we use the "proper" solution. What is the 'right' or 'rails' way to do this?
Using has_many :through, you can specify :uniq as an option, like this:
has_many :parents, :through => :children_parents, :uniq => true

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