views:

78

answers:

1

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)

alt text

A: 

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, i.e.

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
KandadaBoggu
so ContactEmail is a new model which represents a contact-email pair?
Angela
Yes, ContactEmail is the pair.
KandadaBoggu
So would ContactEmail also need to have its own attributes, exactly the same as Email does (but with mailmerged text?) Or is it just a place-holder and the email gets sent and the contents never stored?
Angela
:status => :new is the string "new"?
Angela
hmmm...so is it a nested loop? How do I create a new one, is it new_contact_email(@contact, @email)?
Angela
Look at the updated reply.
KandadaBoggu
Ah, I see --- okay, that's the way I would put into the cotnroller....what is the route and how would I do the form, if we are creating an email instance that will get sent through actionmailer?In other words, contact_email will inherent the body from email, with some mailmerge substitution and maybe even customization. Or will this just allow updating of status....thanks, by the way, for your excellent response.
Angela
What would the restful URL be? Would it be a multiple nested route: contact/1/email/3/contact_email/new?
Angela
Your nested route URL looks fine.
KandadaBoggu
What do I need to do in the routes.rb to make that work?I would like to have a link to create a new contact, such as new_contact_email(@contact,@email) which will then take me a form which will mail-merge the email and set the status.
Angela
Updated the answer take a look.
KandadaBoggu