has_many associations - ruby-on-rails

So, my question is: how to make possible that calls:
Clan.win #to get all won rounds
Clan.blue #to get all rounds when clan was in blue team
or even this:
Clan.matches_win #need to calculate which team won match by counting rounds
Clan.matches_lost
Round model:
class Round < ActiveRecord::Base
belongs_to :match
has_and_belongs_to_many :banned_champions, :class_name => "Champion", :join_table => "banned_champions_rounds"
belongs_to :clan_blue, :class_name => "Clan", :foreign_key => "clan_blue_id"
belongs_to :clan_purple, :class_name => "Clan", :foreign_key => "clan_purple_id"
belongs_to :winner, :class_name => "Clan", :foreign_key => "winner_id"
end
Clan model:
class Clan < ActiveRecord::Base
has_many :players
has_many :rounds
end
Match model:
class Match < ActiveRecord::Base
has_many :rounds
end

In your Clan class:
def win
rounds.where("winner_id = ?", self.id)
end
The others are more or less the same.

Related

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.

Joining one table two times

My db schema:
tournaments(id, ...)
teams(tournament_id, id, ...)
matches(tournament_id, id, team_id_home, team_id_away, ...)
Models:
class Tournament < ActiveRecord::Base
has_many :teams, dependent: :destroy
has_many :matches, dependent: :destroy
...
end
class Team < ActiveRecord::Base
belongs_to :tournament
...
end
class Match < ActiveRecord::Base
belongs_to :tournament
has_many :teams
...
end
I would like to have the following data in my view:
match_id team_id_home team_id_away team_id_home_name team_id_away_name
So, I'm asking for help with the following query (I'm trying to get team's names, but having problem with joining):
#matches = #tournament.matches.where(:tournament => #tournament).joins(:teams).paginate(page: params[:page])
I'm fairly new to rails, but you should be able to setup your associations like this: (going from memory)
class Match < ActiveRecord::Base
belongs_to :tournament
has_one :home_team, :class_name => "Team", :foreign_key => "team_id_home"
has_one :away_team, :class_name => "Team", :foreign_key => "team_id_away"
end
#####
m = Match.first
m.away_team.team_name
m.home_tam.team_name
Or in your case:
#matches = #tournament.matches.paginate(page: params[:page])
I don't think you need the where function: the has_many association tells rails to only pull matching matches.
It is belongs_to, not has_one in Match model.
class Match < ActiveRecord::Base
belongs_to :tournament
belongs_to :home_team, :class_name => "Team", :foreign_key => "team_id_home"
belongs_to :away_team, :class_name => "Team", :foreign_key => "team_id_away"
end
class Team < ActiveRecord::Base
belongs_to :tournament
has_many :matches
end
Now I can use tournament.home_team.name in my view

Rails polymorphic table that has other kinds of associations

I'm currently modeling a Rails 3.2 app and I need a polymorphic association named "archivable" in a table named "archives". No worries with it, but my "archives" table must also belongs_to a "connections" table. I just want to know if there's any constraints from Rails to do that.
You can see the model here
Another detail, my Connection model has twice user_id as foreign key. A user_id as sender and a user_is as receiver. Possible? I think what I did below won't work...
Here are my models associations.
class User < ActiveRecord::Base
has_many :connections, :foreign_key => :sender
has_many :connections, :foreign_key => :receiver
end
class Connections < ActiveRecord::Base
belongs_to :user
has_many :archives
end
class Archive < ActiveRecord::Base
belongs_to :connection
belongs_to :archivable, :polymorphic => true
end
class Wink < ActiveRecord::Base
has_many :archives, :as => :archivable
end
class Game < ActiveRecord::Base
has_many :archives, :as => :archivable
end
class Message < ActiveRecord::Base
has_many :archives, :as => :archivable
end
Do you see anything wrong or something not doable with Rails?
Thank you guys.
I think you want to do this :
class Connections
belongs_to :sender, :class_name => 'User', :foreign_key => 'sender_id'
belongs_to :receiver, :class_name => 'User', :foreign_key => 'receiver_id'
end
class User
has_many :sended_connections, :class_name => 'Connection', :as => :sender
has_many :received_connections, :class_name => 'Connection', :as => :receiver
end
Important : Don't declare 2 times has_many :connections with the same name !

How to trigger multiple counter_cache in one model as has_many :through

I have 3 models(Allen, Bob, Chris) which are polymorphic with Join model. and a User model which connect with the join model.
class Allen < ActiveRecord::Base
has_many :joins, :as => :resource
...
end
class Bob < ActiveRecord::Base
has_many :joins, :as => :resource
...
end
class Chris < ActiveRecord::Base
has_many :joins, :as => :resource
...
end
class Join < ActiveRecord::Base
belongs_to :initiator, :class_name => "User", :foreign_key => "user_id"
:counter_cache => "How to write with 3 different counter cache?"
belongs_to :resource, :polymorphic => true, :counter_cache => :resources_count
end
class User < ActiveRecord::Base
has_many :joins
has_many :allens, :through => :joins, :source => :initiator
has_many :initial_joins, :class_name => "Join"
end
My question is how to write the counter cache for Bob, Chris and Allen in User Model
or you can review it here: https://gist.github.com/1350922
I think, there's no standard way to achieve this. Add an after_create callback to your Allen, Bob and Chris where you would get the list of all Users associated with this particular Bob and recalculate bobs_count for each of them manually.

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