Many-to-many connection and Associations

2020-08-01 03:51发布

问题:

A User can Upload a Clip via the Clips Scaffold, this clip either belongs to a Show and or an Album (Show Controller, Album Controller).

A user can have

  • ONLY ONE SHOW
  • MANY ALBUMS

    What i'm trying to accomplish:

A User can Upload Clips, these clips can be attached to either a Show or/and an Album

For a more detailed overview take a look at the image below:

Problem #1 What i'm not understanding is the associations i must use. My current Models:

User Model:

has_many :clips, dependent: :destroy
has_one :show, dependent: :destroy
has_many :albums, dependent :destroy

Clip Model: belongs_to :user

Show Model: belongs_to :user

Album Model: belongs_to :user

---------------------------------------------------------------------------------

Problem #2 I'm not sure on how to accomplish, that when a user uploads a Clip, he can attach (or assign) it to a Show or Album.

What i did with the Show (because there is only one) was just to call <%= @user.clip %> on the View Page.

That means that every clip a user upload's appears on the Show.

Which is wrong...

Now that i have a Show AND an Album i must grand the user the ability to choose where to attach it (On one of the many albums he have, or his Show).

Or should i go with a solution where the User can Upload a Clip THROUGH the Albums or Show controller (not through the separate Clips Controller)

I really could need some help here :)

回答1:

Your problem #1 is a textbook case of polymorphic association.

class User < ActiveRecord::Base
  has_one         :show,
                  :dependent => :destroy
  has_many        :clips,
                  :dependent => :destroy
  has_many        :albums,
                  :dependent => :destroy
end

class Clip < ActiveRecord::Base
  belongs_to      :user
  belongs_to      :attachable,
                  :polymorphic => true
end

class Show < ActiveRecord::Base
  belongs_to      :user
  has_many        :clips,
                  :as => :attachable
end

class Album < ActiveRecord::Base
  belongs_to      :user
  has_many        :clips,
                  :as => :attachable
end

You can learn more about polymorphic associations at Rails Guides.

Now for your problem #2, assuming you do your migrations as per the guide linked above you'll have two database fields in your clips table:

  • attachable_id - This is the id of the instance of Show or Album that's going to receive the association.
  • attachable_type - This is the class name of the target object, so either Show or Album.

In your upload form, you're going to show a list of shows and/or albums and assign the id to attachable_id and the class name to attachable_type.

I would suggest loading up your initial select with only one class and then replacing its contents via JavaScript in case the user selects the second option. Like so:

<%= f.collection_select :attachable_type, [['Show'], ['Album']], :first, :first, { :selected => 'Show' }, { :include_blank => false } %>
<%= f.collection_select :attachable_id, Show.all, :id, :name %>


回答2:

I think that unless there's some reason they all must belong to the user, you can simplify this a lot by making better use of your clip model.

Change your relationships to this:

User.rb

has_many :clips, dependent: :destroy

Clip.rb

belongs_to :user
has_one :show
has_many :albums

Show.rb

belongs_to :clip

Album.rb

belongs_to :clip

You can see the show by using clip.show and the albums by using clip.albums - individual albums can be called by using clip.albums.find(params[:id])