2016-04-14 57 views
0

我有一个简单的关系:HAS_ONE/belongs_to的方法

Student 
has_one :locker, inverse_of: :student, validate: true, dependent: :nullify 
accepts_nested_attributes_for :locker 

Locker 
belongs_to :student, inverse_of: :locker, touch: true 

我有这样一种形式:

<%= f.simple_fields_for :locker do |l| %> 
    <%= l.input :id, as: :select, 
     collection: @lockers_collection, 
     label: false, 
     value_method: :id, 
     label_method: :number, 
     include_blank: true, 
     input_html: { class: "admin-select2" }, 
     selected: "#{@student.locker ? @student.locker.id : ""}", 
     wrapper: 'admin_vertical_select' -%> 
<% end -%> 

当我创造新的学生,我可以分配一个储物柜(或没有),一切都很简单,并按预期工作。好吧,我不得不添加此两轮牛车到学生的模式,否则Rails的在抱怨找不到记录(解决方案在这里发现了SO):

def locker_attributes=(attributes) 
    if attributes['id'].present? 
    self.locker = Locker.find(attributes['id']) 
    end 
    super 
end 

不管怎么说,我有什么重大的问题是编辑/更新动作。 首先,我需要检查,如果学生目前有一个储物柜或不建现有的一个新的或:

if @student.locker 
    @student.build_locker(id: @student.locker.id) 
else 
    @student.build_locker 
end 

现在我试图找到解决现实问题。 基本上有几种情况可能发生:

  • 学生没有储物柜,也没有储物柜。
  • 学生有一个更衣室,但我想清除它

    在这两种情况下的学生没有更新,因为(我怀疑)储物柜是空的。如何处理这个?

然后还有可能将Locker从一个更改为另一个。 在这种情况下,我以某种方式认为Rails将足够聪明来更新“旧”储物柜。我可以看到old locker上的student_id id为零,但Rails如何做到这一点?问题是我有一个关于Locker的paper_trail,我需要在旧版本变空时进行版本控制。

如何处理空方案?这是我最大的问题。 我是对的还是有更好的方法去做?

THX

回答

0

如果添加inverse_of您协会的车型,如:

  • 学生:has_one :locker, inverse_of: :student
  • 储物柜:belongs_to :student, inverse_of: :locker

您将能够只使用:

@student.build_locker unless @student.locker 

而且您不需要def locker_attributes=(attributes)方法。

要废掉你可以添加以下的动作在某些控制器,这样在更衣室:

@student.locker = nil 
@student.save 
+0

嘿马里奥。我实际上有inverse_of的定义,忘了提及它。我会更新我的问题。无论如何,没有这种方法它就无法工作。 –

+0

更新了问题 –

+0

我不能只是取消并保存一个储物柜。如果学生的其他属性发生了变化,该怎么办?像地址等... –