Proper Rails association setup - ruby-on-rails

Im setting up a reminder service that sends deals via email in relation to a persons interests AND city.. Basically, the user inputs important dates (friends bday, anniversary ect) and the interests of that special person.
I want to send them deals based on 1)the users city and 2)the interests of the related person
How should i setup my associations for the Deal model?
What i have so far..
class User < ActiveRecord::Base
belongs_to :city
has_many :person_interests, :as => :person
has_many :interests, :through => :person_interests
end
class City < ActiveRecord::Base
attr_accessible :name
belongs_to :province
has_many :users
end
class PersonInterest < ActiveRecord::Base
belongs_to :interest
belongs_to :person, :polymorphic => true
end
class Interest < ActiveRecord::Base
has_many :person_interests
end
Thanks!

If a deal could apply to more than one interest, you'd start with something like:
class Deal < ActiveRecord::Base
belongs_to :interests
belongs_to :city
end
class City < ActiveRecord::Base
attr_accessible :name
belongs_to :province
has_many :users
has_many :deals
end
class Interest < ActiveRecord::Base
has_many :person_interests
has_many :deals
end
And then you could do something like
#relevant_deals = #city.deals.where(:interest_id => 'abc')
or
#relevant_deals = #interest.deals.where(:city_id => 'def')

Related

Rails 4: Show List of Items in third level associations

I have Following structure in my rails app.
class Country < ActiveRecord::Base
has_many :states
end
class State < ActiveRecord::Base
has_many :cities
belongs_to :country
end
class City < ActiveRecord::Base
belongs_to :state
end
I want to access to cities from the country model.
e.g. #country.cities.
Also, how can I get the country from city model?
e.g #city.country
Thanks,
Use through option in has_many and delegate for belongs_to:
class Country < ActiveRecord::Base
has_many :states
has_many :cities, through: :states
end
class State < ActiveRecord::Base
has_many :cities
belongs_to :country
end
class City < ActiveRecord::Base
belongs_to :state
delegate :country, to: :state
end

Best way to associate these models?

I have four models, Movies, Person, Cast, and Crew and I'm uncertain on what is best way to associate them all together. Should I use a has many through association or stick with the associations below? Any recommendations would be greatly appreciated.
I want to be able to visit a movie object's show page then be able to list the appropriate cast and crew associated with the movie. In addition, when I visit a Person's show page, I want to list of all their cast roles movies, in addition if they were part of the crew.
class Movie < ActiveRecord::Base
has_many :cast
has_many :crew
end
class Person < ActiveRecord::Base
has_many :cast
has_many :crew
end
class Cast < ActiveRecord::Base
belongs_to :movie
belongs_to :person
end
class Crew < ActiveRecord::Base
belongs_to :movie
belongs_to :person
end
class Movie < ActiveRecord::Base
has_many :cast_memberships
has_many :crew_memberships
has_many :cast_members, :through => :cast_memberships, :source => :person
has_many :crew_members, :through => :crew_memberships, :source => :person
alias_method :cast, :cast_members
alias_method :crew, :crew_members
end
class CastMembership < ActiveRecord::Base
belongs_to :movie
belongs_to :person
end
class CrewMembership < ActiveRecord::Base
belongs_to :movie
belongs_to :person
end
class Person < ActiveRecord::Base
end
class CastMember < Person
has_many :cast_memberships, :foreign_key => :person_id
has_many :roles, :through => :cast_memberships, :source => :movie
end
class CrewMember < Person
has_many :crew_memberships, :foreign_key => :person_id
has_many :jobs, :through => :crew_memberships, :source => :movie
end
> movie = Movie.create! name:"Star Wars"
> cast_member = CastMember.create! name:"Harrison Ford"
> movie.cast << cast_member
> movie.cast # [{name: "Harrison Ford"}]
> cast_member.roles # [{name: "Star Wars"}]
This isn't quite what you need--cast_member.roles should return the characters (["Han Solo"]) not the movies. You could add attributes to the cast_memberships and crew_memberships tables for character data or job descriptions.

Multi-level nested count in ActiveRecord (Rails)

I feel a little out of my depth here. I've got the following relationships:
class User < ActiveRecord::Base
has_many :flights
end
class Flight < ActiveRecord::Base
has_many :flight_legs
belongs_to :user
end
class FlightLeg < ActiveRecord::Base
belongs_to :departure_airport, :class_name => "Airport"
belongs_to :arrival_airport, :class_name => "Airport"
end
class Airport < ActiveRecord::Base
belongs_to :country
has_many :flight_legs_arriving_here, :class_name => "FlightLeg",
:foreign_key => "arrival_airport_id"
has_many :flight_legs_departing_here, :class_name => "FlightLeg",
:foreign_key => "departure_airport_id"
end
class Country < ActiveRecord::Base
attr_accessible :name
has_many :airports
end
I want to get a list of users by the number of countries that they have visited, and a separate query which will return the number of countries a user has visited. Does anyone have any idea how to do this? I am sort of lost with the details of the documentation on this one.

Model associations for a contest

I'm new to rails and working on an app that has the following situation:
Users have skills (e.g rafting, dancing)
Users participate in contests
Contest measures multiple skills
At the end of each contest, each user gets a score (e.g dancing: 5, rafting: 4)
Whats the best way to model this ?
Thanks,
This got nasty :s At the end I was actually not sure if this is the right way
class Skill < ActiveRecord::Base
has_many :skill_scores
has_many :user_skills
end
class UserSkill < ActiveRecord::Base
belongs_to :user
belongs_to :skill
end
class SkillScore < ActiveRecord::Base
belongs_to :user
belongs_to :contest
belongs_to :skill
end
class User < ActiveRecord::Base
has_many :skills
has_many :contests, :through => :contest_participations
has_many :skill_scores
end
class Contest < ActiveRecord::Base
has_many :users, :through => :contest_participations
has_many :skill_scores
end
class ContestParticipation < ActiveRecord::Base
belongs_to :user
belongs_to :contest
end

How can I join the same 2 models twice in Rails?

I have an app with country preferences. A user will have 2 types of country preferences - event and research. In the future there may be more. I was leaning more towards having 2 tables to represent this over using STI. I'm having a bit of trouble configuring Rails elegantly to do this. I could hack it but I would rather do this by Rails convention. What I want is something like this:
class User < ActiveRecord::Base
has_many event_countries, :through => :event_countries, :class_name => 'Country'
has_many research_countries, :through => :research_countries, :class_name => 'Country'
end
class EventCountry < ActiveRecord::Base
belongs_to :country
belongs_to :user
end
class ResearchCountry < ActiveRecord::Base
belongs_to :country
belongs_to :user
end
class Country < ActiveRecord::Base
...
end
This doesn't work though. Given this "pseudo code" does anyone know how to actually implement this in Rails?
I think you're going about declaring them wrong, because this should work properly. That's what the :through directive is for:
class User < ActiveRecord::Base
has_many :event_countries
has_many :countries_with_events,
:through => :event_countries,
:source => :country
has_many :research_countries
has_many :countries_with_researches,
:through => :research_countries,
:source => :country
end
class EventCountry < ActiveRecord::Base
belongs_to :country
belongs_to :user
end
class ResearchCountry < ActiveRecord::Base
belongs_to :country
belongs_to :user
end
class Country < ActiveRecord::Base
# ...
end
A lot of the awkwardness comes from the labels you've chosen for the tables. Although they'd seem reasonable at first glance, the way you use them ends up making them difficult.
You might want to call research_countries something like user_research_countries so that the relationship name can be user.research_countries as the :through:
class User < ActiveRecord::Base
has_many :user_event_countries
has_many :event_countries,
:through => :user_event_countries,
:source => :country
has_many :user_research_countries
has_many :research_countries,
:through => :user_research_countries,
:source => :country
end
class UserEventCountry < ActiveRecord::Base
belongs_to :country
belongs_to :user
end
class UserResearchCountry < ActiveRecord::Base
belongs_to :country
belongs_to :user
end
class Country < ActiveRecord::Base
# ...
end
You can refactor this even further by adding a field to the user-country association table that includes one or more flags, which in this case would be research or event or whatever you require later:
class User < ActiveRecord::Base
has_many :user_countries
has_many :event_countries,
:through => :user_countries,
:source => :country,
:conditions => { :event => true }
has_many :research_countries,
:through => :user_countries,
:source => :country,
:conditions => { :research => true }
end
class UserCountry < ActiveRecord::Base
belongs_to :country
belongs_to :user
# * column :event, :boolean
# * column :research, :boolean
end
class Country < ActiveRecord::Base
# ...
end

Resources