I have a simple rails app where I am trying to establish the relationship between two models.
I have a plan model and a subscription model.
A subscription will only ever have 1 plan but plans can belong to many subscriptions.
As there is no belong to many relationship I am guessing that the best way to create this is using has_and_belongs_to_many with a join table of plan_subscription - is this correct?
Assuming this is correct how do I ensure that my subscription only ever has a single plan created?
The current code I have is as follows:
class Subscription < ApplicationRecord
has_and_belongs_to_many :plans
end
class Plan < ApplicationRecord
has_and_belongs_to_many :subscriptions
end
Any help would be much appreciated.
has_and_belongs_to_many association is many to many association and you wrote subscription will only ever have 1 plan, plans can belong to many subscriptions so in this case your association is wrong.Your association will be like this:
class Plan < ActiveRecord::Base
has_many :subscriptions
end
class Subscription < ActiveRecord::Base
belongs_to :plan
end
Related
I have two models User and Project which are in has_and_belongs_to_many association
The user model has a column status
i can access the status of a user who is in project like
project.user.status
but a user can be in different projects i want his status to be on project level instead of on his id
If I understand your question correctly, the problem is that you need to associate the status of the user to one of potentially many projects that the user is associated with, but you are associating a single status to a single user instead of the project.
In that event, you need to abstract this association to an additional model, for instance "UserProjectStatus" which would be associated with both the User and the Project. You can do this using the has_many, through association. This would end up with something along the lines of:
class Project < ApplicationRecord
has_many :user_project_statuses
has_many :users, through :user_project_statuses
end
class UserProjectStatus < ApplicationRecord
belongs_to :user
belongs_to :project
end
class User < ApplicationRecord
has_many :user_project_statuses
has_many :projects, through :user_project_statuses
end
There is a good overview of this any many other Rails ActiveModel associations at https://guides.rubyonrails.org/association_basics.html#the-has-one-through-association.
Hope this helps!
I'm uncertain of the best approach to model conversation relationships.
My application has Users, Conversations, UserConversations, Venues, & VenueConversations.
Users can have many Conversations & Conversations can have many Users. Thus, the bridging table (UserConversations).
Venues can also have Conversations and these Conversations can also have many Users. Thus, the bridging table (VenueConversations)
I've tried it with polymorphic associations but then Messages in the Conversations became difficult to manage. Also, a while back I asked a question on Stack and someone said I should steer clear of polymorphic associations at all costs.
I hope to do this properly so that querying doesn't become a nightmare in the future.
I'd also like to state I'd like to have one Conversation model because one day they'll share a lot of behavior.
User.rb
class User < ApplicationRecord
has_many :user_conversations
has_many :conversations, through: :user_conversations
has_many :venue_conversations
has_many :conversations, through: :venue_conversations
end
UserConversation.rb
class UserConversation < ApplicationRecord
belongs_to :user
belongs_to :conversation
end
Venue.rb
class Venue < ApplicationRecord
has_many :venue_conversations
has_many :conversations, through: :venue_conversations
end
VenueConversations.rb
class VenueConversations < ApplicationRecord
belongs_to :user
belongs_to :venue
belongs_to :conversation
end
The problem I'm having now is that when I do User.first.conversations I only find one of the types of conversations a User could have(Private vs Venue). It reflects the last definition I gave to has_many :conversations in the User.rb model. Perhaps a scope is in order? How would I make a distinction between private & venue conversations as well?
Please advise me on how I could resolve this or take a better approach
I'm trying to understand a rails model association and having trouble figuring out what association I need to use:
Here's my app Models
Company ---- Subscription ---- SubscriptionType
The SubscriptionType has a list of 3 different types of subscriptions and their associated price.
A Company has_one :subscription.
A Subscription will belong_to :company.
It also has other fields, such as trial_start_date, trial_end_date, charge_date, etc.
At first, I thought that Subscription has_one SubscriptionType and SubscriptionType has_many Subscriptions however that relationship doesn't seem to work in my subscription_spec.rb
it { should have_one(:subscription_type) }
But that gives me the following error, which indicates that this relationship won't work since I don't want to have tons of records in the SubscriptionType table:
Expected Subscription to have a has_one association called subscription_type (SubscriptionType does not have a subscription_id foreign key.)
Can someone help me wrap my head around this?
The difference between has_one vs belongs_to is all about where the foreign key lives.
Subscription has_one :subscription_type means that SubscriptionType has a subscription_id column and belongs to only one Subscription.
Subscription belongs_to :subscription_type means that Subscription has a subscription_type_id column and SubscriptionType can belong to multiple Subscriptions.
So to answer your question, the correct relationship here is
class Subscription < ApplicationRecord
belongs_to :subscription_type
end
class SubscriptionType < ApplicationRecord
has_many :subscriptions
end
You can set the associations like this:
class Company < ApplicationRecord
has_one :subscription
end
# subscriptions table should have columns company_id and subscription_type_id
class Subscription < ApplicationRecord
belongs_to :company
belongs_to :subscription_type
end
class SubscriptionType < ApplicationRecord
has_many :subscriptions
end
With this setup, the associated objects can be accessed as:
company = Company.find(1)
# to get subscription object with company_id: 1
company.subscription
# to get subscription_type object of the company's associated subscription
company.subscription.subscription_type
# to get all subscriptions of a particular subscription_type
SubscriptionType.last.subscriptions
Then, your subscription_spec.rb looks like:
it { should belong_to(:company) }
it { should belong_to(:subscription_type) }
I'm a little confused on which type of association I should set up in my application.
I have these three models: Booking, Availability and Facility
A facility puts up 1 hour blocks of available time. So I'd say Availability: belongs_to :facility.
I'm trying to represent that a booking could have many availabilities. In that if I book from 1-3PM that's two 1 hour blocks and I'd like for that to be represented in 1 record in the Bookings table.
I was thinking I should set up Bookings: has_many :availability
but then I was reading about has_many though and I wasn't sure if it would be more appropriate to do Facilities has many Bookings through Availability...?
I would absolutely do a has_many :through association here, but I'd make the association between Availability and Booking slightly different than a typical has_many :through association:
class Facility < ActiveRecord::Base
has_many :availabilities
has_many :bookings, through: :availabilities
end
class Availability < ActiveRecord::Base
belongs_to :facility
has_one :booking
end
class Booking < ActiveRecord::Base
belongs_to :availability
end
The reason I prefer this association style is because in a typical has_many :through, you have two entities sharing relationships with one another through a third entity (e.g. Patients and Doctors sharing a relationship through an entity called Appointment, as explained by the Rails guides). This example is different, however, in that Booking shouldn't hold any positive relationship to Facility--the relationship should merely be a by-product of an open Availability.
I have the following situation:
I have a Club which can have several Teams, and a Team can have several Players.
However, the Players that a Team has will vary each year. I am wondering how could I put somehow season information into the picture in a way that the user will be able to add/remove Players each season and be able to see Players of a team from previous seasons.
So, given the following models:
Club has_many Team
Team belongs_to Club
Team has_many Players
How would I make it so that Team has_many Players depends on the Season (2013/2014 - 2012/2013..)
There are two ways to do it:
One is to create another relation for the SEASON and create a ternary relationship (http://www.databasedesign.co.uk/bookdatabasesafirstcourse/chap3/chap3.htm)
The tables would look something like this:
PLAYER(id,...)
TEAM(id,name,...,club_id)
SEASON(id,season_name,...)
SEASON_PARTICIPATION(id,player_id,season_id,team_id)
And the ActiveRecord associations would be:
class Club < ActiveRecord::Base
has_many :teams
end
class Team < ActiveRecord::Base
belongs_to :club
has_many :players, through: :season_participations
end
class Player < ActiveRecord::Base
belongs_to :teams, through: :season_participations
end
class Season < ActiveRecord::Base
has_many :players, through: :season_participations
end
class SeasonParticipation < ActiveRecord::Base
belongs_to :player
belongs_to :team
belongs_to :season
end
More documentation on ActiveRecord associations can be found here: http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association
Another way of doing this is to skip the SEASON relation all together and have it as a simple attribute in the SEASON_PARTICIPATION relation. So instead of a season_id you would have the name of the season in the SEASON_PARTICIPATION (see diagram 2). Having a separate SEASON relation gives you the opportunity to store more information about the season, like start-date/end-date etc. Eventually you could also add division information in another relation.
There's many ways you could do this. Here's a few that spring immediately to mind.
Add a season column to the Player model. Have the Player's season attribute be set on create via callback. If the season != current_season, prevent the user from creating, updating, or destroying the player.
Use the updated_at column which is already provided in the Player model to do basically the same thing. Create a method which parses the datetime and converts it into something more useful to you, probably a season number or something along those lines.