1

I have over thought this to the point that I'm only getting confused now.

I have a Rails app with the following as models: User, Site, Tutorial, TutorialStep.

A user can create many tutorials and each tutorial has a site it lives on, and each tutorial has many tutorial steps.

The model I'm having the issue with is Site.

A user has many tutorials and has many tutorials steps through tutorial. A tutorial belongs to a user and has many tutorial steps and lastly a tutorial step belongs to a tutorial.

Now should a site belong to a user and a tutorial, or just a tutorial?

stevenpslade
  • 310
  • 1
  • 18

4 Answers4

1

I would structure the relations as follows:

class User < ApplicationRecord
  has_many :tutorials
  has_many :sites, through: :tutorials
  ...
end

class Site < ApplicationRecord
  has_many :tutorials
  has_many :users, through: :tutorials
  ...
end

class Tutorial < ApplicationRecord
  has_many :tutorial_steps
  belongs_to :user
  belongs_to :site
  ...
end

class TutorialStep < ApplicationRecord
  belongs_to :tutorial
  ...
end

Making a Site belong to a User Binds that site to a single user only, which then means that multiple users cannot place tutorials on the same site, you would have to make duplicate entries of the same site to be able to achieve this, which in my opinion is not very good model design, because if in real life multiple users have different tutorials on the same site, you want to be able to reflect that same behaviour in your models and data. Therefore if you want to be able to reference sites from a User, and reference users from a Site, I would recommend using a has many through relation on the table that links them, ie the tutorial table, like I have show above.

John Hayes-Reed
  • 1,358
  • 7
  • 13
  • Thanks! This makes a lot of sense. Other answers are close to this but are missing the `has_many :users, through: :tutorials` on `Site`. As per your point, this is important to have because then I can reference sites from a User. – stevenpslade Mar 23 '17 at 17:22
0

User

has_many :tutorials

Site

has_many :tutorials

Tutorial

has_many :tutorial_steps
belongs_to :user
belongs_to :site

Tutorial would need site id and user id to correctly map association to user and site

Tutorial Table (... user_id,site_id)

SoWhat
  • 5,564
  • 2
  • 28
  • 59
0

It should look like this,

user.rb

has_many :tutorials
has_many :tutorial_steps, through: :tutorials

site.rb

has_many :tutorials

tutorial.rb

has_many :tutorial_steps
belongs_to :user
belongs_to :site

tutorial_step.rb

belongs_to :tutorial
has_one :user, through: :tutorial
has_one :site, through: :tutorial

Hope that helps!

Rajdeep Singh
  • 17,621
  • 6
  • 53
  • 78
  • Thanks for your input! John's answer is pretty much this but also adds `has_many :users, through: tutorials` on the Site model and vice versa on the User model. His point was that this way you can reference sites from a `User`. What are your thoughts on that? – stevenpslade Mar 23 '17 at 17:24
0

As far as i understand from your question you can use has_one relation.

has_one : Specifies a one-to-one association with another class

you can create a has_one relation with site and tutorial

app/models/user.rb

has_many :tutorials,->{ includes :site}
has_many :tutorial_steps, through: :tutorials

includes is eager loading technique which lets you to fetch site along with the tutorial relation

app/models/tutorial.rb

belongs_to :site
belongs_to :user
has_many :tutorial_steps

app/models/site.rb

  has_one :tutorial

app/models/tutorial_step.rb

belongs_to :tutorial
Vishal Taj PM
  • 1,339
  • 11
  • 23
  • Thanks for the input Vishal, however a one-to-one relationship won't work here because even though a tutorial has one site, a site can have many tutorials. I should have made that more clear, thank you. – stevenpslade Mar 23 '17 at 17:25
  • in that case you can go with the @john post. happy that you got a solution for it. :) – Vishal Taj PM Mar 23 '17 at 17:46