Как мне использовать has_many: through и in_place_edit? - PullRequest
1 голос
/ 06 мая 2010

У меня есть две модели: Campaign и Contact.

A Campaign has_many Contacts.

A Contact has_many Campaigns.

В настоящее время каждый Contact имеет атрибут contact.date_entered,Кампания использует эту дату в качестве результата для обратного отсчета до различных Событий, которые принадлежат Кампании.

Однако существуют ситуации, когда Кампанию для определенного Контакта может потребоваться отложить на X дней.В этом случае campaigncontact.delaydays = 10.

В некоторых случаях кампания должна быть полностью остановлена ​​для конкретного контакта, поэтому на данный момент я установил campaigncontact.delaydays = 1. (Существуют ли серьезные проблемы с этим?)

По умолчанию я предполагаю, что никакого рекламного контакта кампании не существует (но не уверен, как это работает?)

Итак, вот что я пытался сделать:

class Contact < ActiveRecord::Base
  has_many :campaigncontacts
  has_many :campaigns, :through => :campaigncontacts
end

class Campaign < ActiveRecord::Base
  has_many :campaigncontacts
  has_many :contacts, :through => :campaigncontacts
end

script/generate model campaigncontact campaign_id:integer contact_id:integer delaydays:integer

class Campaigncontact < ActiveRecord::Base
  belongs_to :campaign
  belongs_to :contact
end

Итак, вот вопрос: верно ли приведенное выше?Если да, то как разрешить пользователю редактировать задержку кампании для определенного контакта.

Сейчас я хочу сделать это из представления контактов.

Это то, что япробовал:

в контроллере контактов (?)

  in_place_edit_for :campaigncontact, column.delaydays

и в представлении

<%= in_place_editor_field :campaigncontact, :delaydays %>

как мне правильно это сделать?

Ответы [ 2 ]

1 голос
/ 15 мая 2010

Я бы добавил целочисленное поле к вашему ресурсу Campaigncontacts под названием days_to_delay_communication_by, поскольку эта информация относится к ассоциации кампании и контакта, а не самого контакта.

в вашей миграции:

def self.up
  add_column(:campaigncontacts, :days_to_delay_communication_by, :integer)
end

def self.down
  remove_column(:campaigncontacts, :days_to_delay_communication_by)
end

Теперь вы можете установить это значение:

campaigncontact = Campaigncontacts.find(:first, :conditions => { :campaign_id => campaign_id, :contact_id => contact_id })
campaigncontact.days_to_delay_communication_by = 10

Тогда на стороне администратора вашего приложения вы можете иметь контроллер и представление для сообщений кампании, которое позволяет вам установить поле days_to_delay_communication_by для CampaignContacts. Я могу рассказать вам об этом подробнее, если вам интересно, но я думаю, вы поняли идею.

Затем вам нужно будет запустить некоторый фоновый процесс (возможно, задание cron или использовать плагин delayed_job ), чтобы найти сообщения, которые еще не произошли, и заставить их произойти, когда дата прошла. Вы можете сделать это в граблях, например так:

namespace :communications do
  namespace :monitor do
    desc 'Monitor and send communications for campaigns'
    task :erma => :environment do
      Rails.logger.info "-----BEGIN COMMUNICATION MONITORING-----"

      unsent_communications = Communication.all(:conditions => { :date_sent => nil})
      unsent_communications.each do |communication|
        Rails.logger.info "**sending communication**"
        communication.send if communication.time_to_send < Time.now
        Rails.logger.info "**communication sent**"
      end

      Rails.logger.info "-----END COMMUNICATION MONITORING-----"
    end #end erma task
  end #end sync namespace
end #end db namespace

Тогда ваша работа cron будет выглядеть примерно так:

cd /path/to/application && rake communications:monitor RAILS_ENV=production

Кроме того, я хотел бы рассмотреть вопрос об изменении названия вашей модели объединения на что-то более описательное для ее цели, например, членство, кампания имеет много членств и контакт имеет много членств. Тогда членство имеет поле days_to_delay_communication.

0 голосов
/ 10 мая 2010

Хороший способ сделать это - использовать атрибут «fake» в вашей модели контактов, например:

class Contact < ActiveRecord::Base
  has_many :campaigncontacts
  has_many :campaigns, :through => :campaigncontacts

  attr_accessor :delay

  def delay #edit
    self.campaigncontacts.last.delaydays
  end

  def delay=(val)
    self.campaigncontacts.each do |c|
      c.delaydays = val
    end
  end
end

Затем просто установите in_place_editor для этого поддельного поля:

in_place_edit_for :contact, :delay

и

<%= in_place_editor_field :contact, :delay %>

Я не уверен, что точно понял, чего вы хотели достичь, но я надеюсь, что это, по крайней мере, укажет вам правильное направление.

...