简体   繁体   中英

How do I do a has_many through association on a has_many through association in rails?

Warning: I may have the wrong 'problem statement' but here it goes:

A Campaign has many Contacts.

A Campaign has many Emails.

Therefore, a Contact has many Emails through a Campaign.

And an Email can have many Contacts through a Campaign.

Each Contact-Email pair has its own unique Status (status1, status2, etc).

Each Status (for a Contact-Email pair) will have its own User.

I do not know how to model Status, or User. Currently the immediate challenge is Status.

(see diagram below)

替代文字

Solution below is assuming that status can be represented as a string.

class Campaign < ActiveRecord::Base
  has_many :contacts
end

class Contact < ActiveRecord::Base
  belongs_to :campaign
  has_many :contact_emails
  has_many :emails, :through => :contact_emails   
end

class ContactEmail < ActiveRecord::Base
  belongs_to :contact
  belongs_to :email
  belongs_to :user
  # add a column called status 
end

class Email < ActiveRecord::Base
  has_many :contact_emails
  belongs_to :contacts, :through => :contact_emails
end

Adding emails to contact:

contact_email = @contact.contact_emails.build(:user => current_user, 
      :email => @email, :status => "status1")

contact_email.save

OR

@contact.contact_emails.create(:user => current_user, 
  :email => @email, :status => "status1")

OR create multiple:

@contact.contact_emails.create(
  [
    {
      :user => current_user, 
      :email => @email, 
      :status => "status1"
    },
    {
      :user => current_user, 
      :email => @email2, 
      :status => "status2"
    }
  ]
)

Edit 2 Nested resources for ContactEmail.

map.resources :contacts, has_many :contact_emails

URL for ContactEmail

/contacts/1/contact_emails/new #new
/contacts/1/contact_emails/2/edit #edit

The URL does not have the email id. You can pass the email_id as a query parameter, ie

new_contact_contact_email_path(@contact, :email_id => @email)

In your ContactEmailsController:

def new
  @contact = Contact.find(params[:contact_id])
  @email   = Email.find(params[:email_id])
  @contact_email = @contact.contact_emails.build(:email => @email)
end

In your view set email_id as hidden field.

In the create method perform the save.

def create
  @contact = Contact.find(params[:contact_id])
  @contact_email = @contact.contact_emails.build(params[:contact_email])
  if @contact_email.save
    # success
  else
    # error
  end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM