2014-08-28 82 views
0

我想创建一个名为'Persona'的模型(它属于User模型)。用户在表单中选择一个名称,然后单击创建按钮,因此我需要角色模型中的属性“名称”。我还希望Persona模型具有角色名称的小写版本,所以我需要第二个属性'downcase_name'。例如,用户可以选择角色的名字为Fooey Barman,所以downcase_name将是fooey酒保。创建一个模型

我的问题是,你如何初始化downcase_name属性?你把它放在Persona控制器中吗?在新的或创建的方法?例如:

def create 
    @persona = Persona.new(persona_params) 
    @persona.downcase_name = @persona.name.downcase 
    if @persona.save 
    flash[:success] = "Welcome, " + @persona.name 
    redirect_to @persona 
    else 
    render 'new' 
    end 
end 

还是你把它放在模型中?

class Persona < ActiveRecord::Base 
    before_create :make_downcase_name 
    validates :name, presence: true, length: { maximum: 50 } 
    private 
    def make_downcase_name 
     self.downcase_name = name.downcase 
    end 
end 

或者也许这样?

class Persona < ActiveRecord::Base 
    validates :name, presence: true, length: { maximum: 50 } 
    validates :downcase_name, presence: true 
end 

编辑:

所以,我是正确的思维做的是在模型的方式,用before_save和验证,这样?:

class Persona < ActiveRecord::Base 
    before_save :make_downcase_name 
    validates :name, presence: true, length: { maximum: 50 } 
    validates :downcase_name, presence: true 
    private 
    def make_downcase_name 
     self.downcase_name = name.downcase 
    end 
end 

回答

0

使用before_*回调看起来非常习惯。或者,您还可以在控制器中创建一个服务对象(如PersonaCreator),以处理逻辑并在模型上设置适当的属性。

请注意,before_create将只被调用一次,这意味着如果用户稍后更改角色的名称,则不会调用回调。您可能想要执行类似before_save的操作,并检查名称是否已更改。

+0

@fivedigit博客文章提醒您不要使用特定类型的回调用法,例如,延伸到模型主要职责之外的回调 - 这似乎是,正如您在答案中所述。 – 2014-08-28 16:55:23

+0

恐怕我不明白。你是说我需要把这样的东西放在控制器的某个地方:downcase_name = name.downcase。 – Bazley 2014-08-29 17:13:17

+0

不是。我在说,之前回调的使用非常好,非常常见。但是,如果您发现自己处于有很多回调的情况,那么将逻辑移至单独的对象(PersonaCreator)可能会更好。该对象将在控制器中实例化,并传递请求参数。在它内部会创建一个'Persona'模型的新实例,执行逻辑(设置downcase_atribute等)并将未保存的实例返回给控制器进行保存(以便您可以轻松处理验证错误)。 – 2014-08-29 21:00:19