我有几个控制器,每个控制器采用不同类的实例(电子邮件,电话,信件等),他们都必须经历同样的替换:
@email.message.gsub!("{FirstName}", @contact.first_name)
@email.message.gsub!("{Company}", @contact.company_name)
@email.message.gsub!("{Colleagues}", @colleagues.to_sentence)
@email.message.gsub!("{NextWeek}", (Date.today + 7.days).strftime("%A, %B %d"))
@email.message.gsub!("{ContactTitle}", @contact.title )
所以,例如,@ call.message for Call,@ letter.message for Letter,etcetera。
这不是很干。我尝试了以下方法:
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
def message_sub(asset, contact, colleagues)
asset.message.gsub!("{FirstName}", contact.first_name)
asset.message.gsub!("{Company}", contact.company_name)
asset.message.gsub!("{Colleagues}", colleagues.to_sentence)
asset.message.gsub!("{NextWeek}", (Date.today + 7.days).strftime("%A, %B %d"))
asset.message.gsub!("{ContactTitle}", contact.title )
end
end
因此,在信件控制器中有这个:
@letter = Letter.find(params[:letter]) #:letter was passed as a hash of the letter instance
message_sub(@letter, @contact, @colleagues)
@contact_letter.body = @letter.body
但上述方法无效。
答案 0 :(得分:2)
要直接回答您的问题,您需要一个模块。您可以将它放在lib目录中。
module MessageSubstitution
def message_sub(asset, contact, colleagues)
asset.message.gsub!("{FirstName}", contact.first_name)
asset.message.gsub!("{Company}", contact.company_name)
asset.message.gsub!("{Colleagues}", colleagues.to_sentence)
asset.message.gsub!("{NextWeek}", (Date.today + 7.days).strftime("%A, %B %d"))
asset.message.gsub!("{ContactTitle}", contact.title )
end
end
然后在您的控制器中
class MyController < ApplicationController
include MessageSubstitution
def action
...
message_sub(@letter, @contact, @colleagues)
end
end
然而,正如一些人已经指出的那样,这在模型层面可能更好:
module MessageSubstitution
def substituted_message(contact, colleagues)
message.gsub("{FirstName}", contact.first_name).
gsub("{Company}", contact.company_name).
gsub("{Colleagues}", colleagues.to_sentence).
gsub("{NextWeek}", (Date.today + 7.days).strftime("%A, %B %d")).
gsub("{ContactTitle}", contact.title )
end
end
然后您将在模型级别中包含哪些内容,然后在控制器中调用@letter.substituted_message(@contact, @colleagues)
然而,我有点困惑,你发布的内容不起作用。如果它在ApplicationController上定义它应该工作。基于模块的解决方案仍然更好IMO。
答案 1 :(得分:1)
我认为我们缺少解决此问题所需的信息。查看本指南的第3部分:Debugging Rails Applications
逐步执行代码并检查每个点的变量,看看它们是否符合预期。
如果您有时间,请务必阅读整篇指南。它为Rails编程提供了一套宝贵的工具。
作为旁注,您提供的代码感觉它更适合在模型中而不是在控制器中。你的模型可能是Single Table Inheritance的一个很好的候选者,或者你的模型非常相似,你可以将它们压缩成一个涵盖你需要的更通用的模型。如果这些选项中的任何一个都很合适,您可以将message_sub
移出控制器并进入模型。
答案 2 :(得分:0)
问题可能在于gsub!适用于ActiveRecord返回的String对象的实例。要通知ActiveRecord属性更改,您应该调用方法message=(value)
。所以,你的方法是这样的:
def message_sub(asset, contact, colleagues)
asset.message = asset.message.
gsub("{FirstName}", contact.first_name).
gsub("{Company}", contact.company_name).
gsub("{Colleagues}", colleagues.to_sentence).
gsub("{NextWeek}", (Date.today + 7.days).strftime("%A, %B %d")).
gsub("{ContactTitle}", contact.title )
end
(我拿了一些艺术许可来连接gsub方法,但这一切都符合你的口味)
答案 3 :(得分:0)
目前尚不清楚问题是关于重用控制器上的方法(如标题所示)还是最佳的消息模板方法。 要在整个控制器中重用该方法,我想您已经通过使用公共类自己回答了这个问题。然而,正如Awgy所说,这个位在模型中可能比在Controller中更好。
要模板消息,您可以使用ERB而不是gsub或只是'eval'您的字符串 (如果您在邮件中使用#{}而不是{})
firstName=contact.first_name
company = company_name
...
asset.message = eval "\"#{asset.message}\""
(您甚至可以将直接联系作为'绑定'传递给eval函数。
答案 4 :(得分:0)
就个人而言,我不会将此委托给控制器,这不是Presenter Pattern的用途吗?