当我尝试使用Form Object
和Service
创建宣传活动时,我遇到了一些麻烦。在我的应用程序中,我有各种类型的Promotion
,我在:type
列中使用单表继承存储它们。我有促销类型的子类,例如Promotion::CompensationScheme
,Promotion::CouponCampaign
,Promotion::RulesMatch
..等。
在 promotions / new.html.slim :
中= form_for(@promotion_new_form), url: admin_promotions_path do |f|
= f.text_field :name
= f.select :type
:type
select的选项哈希是
{'Coupon Campaign' => 'Promotion::CouponCampaign', 'Rules Match' => 'Promotion::RulesMatch'}
在 PromotionNewForm 类(表单对象)中,我检查表单字段的有效性,并将创建过程传递给名为Promotion::CreateCampaign
的服务。
在 Promotion :: CreateCampaign (服务对象)中:
class Promotion::CreateCampaign < AppService
def initialize params
@promotion_class = params[:type].constantize
@params = params.except!(:type)
end
def call
promotion = @promotion_class.new(@params)
puts promotion.inspect
SuccessStatus.new(promotion)
end
end
在 promotions_controller :
中 def create
results = @promotion_new_form.submit(params[:promotion_new_form])
if results.success?
puts results.data.inspect
# redirect_to edit_admin_promotion_path(results.data)
else
render 'new'
end
end
我现在有这个错误:
Admin :: PromotionsController #create
中的ActiveModel :: ForbiddenAttributesError
基本上说明我的服务对象中的行promotion = @promotion_class.new(@params)
具有禁止的属性。我知道通常如果您在控制器中处理表单,则需要strong_parameters
并使用params.permit()
让params通过..但现在我在服务对象中处理它。我不知道为什么我仍然要这样做,如果是这样我怎么能这样做..
答案 0 :(得分:1)
您正在将params[:promotion_new_form]
传递给您的服务类。 params
是ActionController::Parameters
类的实例。当活动模型接收到此类的一个实例时,它将应用strong_parameters
检查。
所以,你有几个选择。
将已清理的params
传递给您的服务。
results = @promotion_new_form.submit(params.require(:promotion_new_form).permit(:your, :promotion, :fields))
将params的原始Hash
传递给您的服务,并在那里过滤/验证模型属性。
results = @promotion_new_form.submit(params[:promotion_new_form].to_unsafe_hash)
不要使用质量分配方法(create
,new
,update_attributes
等),而是逐个初始化每个属性。
# Controller
results = @promotion_new_form.submit(params[:promotion_new_form])
# Service
promotion = @promotion_class.new
promotion.field1 = @params.field1
promotion.field2 = @params.field2
SuccessStatus.new(promotion)