我如何使用has_many:through和in_place_edit?

时间:2010-05-06 05:22:47

标签: ruby-on-rails ruby has-many-through

我有两个模型:广告系列和联系人。

广告系列has_many通讯录。

联系has_many广告系列。

目前,每个联系人都有一个contact.date_entered属性。 Campaign使用该日期作为事件来倒数到属于Campaign的不同事件。

但是,在某些情况下,特定联系人的广告系列可能需要延迟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

所以,问题是:上述是否正确?如果是,我如何允许用户编辑特定联系人的广告系列延迟。

目前,我希望从联系人视图中这样做。

这就是我的尝试:

在Contact控制器(?)

  in_place_edit_for :campaigncontact, column.delaydays

在视图中

<%= in_place_editor_field :campaigncontact, :delaydays %>

我怎样才能做到对不对?

2 个答案:

答案 0 :(得分:1)

我会在您的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

然后,在您的应用程序的管理员端,您可以拥有一个控制器和一个广告系列通信视图,可让您为campaigncontacts设置days_to_delay_communication_by字段。如果你有兴趣,我可以为你进一步扩展这个,但我想你明白了。

然后你需要运行某种类型的后台进程(可能是一个cron作业,或使用delayed_job plugin)来查找尚未发生的通信,并在日期发生时让它们发生通过。您可以在rake任务中执行此操作:

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字段。

答案 1 :(得分:0)

执行此操作的一种好方法是在Contact模型上使用“假”属性,如下所示:

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 %>

我不确定我到底想要完成什么,但我希望这至少可以指出你正确的方向。