2016-02-11 52 views
1

我有一個Company模型和一個Employer模型。 Employerbelongs_to :companyCompanyhas_many :employers。在我的Employer模型,我有以下驗證:ActiveRecord驗證包含在列表中 - 列表未在創建新關聯模型後更新

validates :company_id, inclusion: {in: Company.pluck(:id).prepend(nil)} 

我運行到哪裏上述驗證失敗的問題。這裏是一個控制器動作設置示例將導致驗證失敗:

company = Company.new(company_params) 
# company_params contains nested attributes for employers 

company.employers.each do |employer| 
    employer.password = SecureRandom.hex 
end 

company.employers.first.role = 'Admin' if client.employers.count == 1 

company.save! 
admin = company.employers.where(role: 'Admin').order(created_at: :asc).last 

admin.update(some_attr: 'some_val') 

在示例代碼段的最後一行,admin.update將失敗,因爲驗證檢查,看看是否company_id包括在清單,它不是,因爲清單是在company保存之前生成的。

顯然有一些解決方法,比如抓取company.id的值,然後用它來定義admin,但這看起來像是一個迂迴的解決方案。我想知道的是如果有更好的方法來解決這個問題。

更新

顯然,可能的解決辦法,我建議甚至不工作。

new_company = Company.find(company.id) 
admin = new_company.employers.where(role: 'Admin').order(created_at: :asc).last 
admin.update 
# Fails validation as before 

回答

2

我不知道如果我完全理解你的問題,但有一個明顯的缺陷在你的代碼

validates :company_id, inclusion: {in: Company.pluck(:id).prepend(nil)} 

驗證是在該類級配置,所以不會與該模型的更新一起工作良好(不會在隨後的驗證中重新評估)。

,你可以在使用塊列入,所以你可以嘗試這樣做,以及在文檔狀態:

validates :company_id, inclusion: {in: ->() { Company.pluck(:id).prepend(nil) }} 

從我的角度來看,你甚至不應該這樣做驗證,但有一個數據庫約束沒有那個列。

+0

我試過你的建議,但它不起作用。當我調用'new_company.save'或'new_company.update(params)'時,我得到'錯誤的參數數量(1代表0)'。我現在只是禁用了驗證。似乎創造了比解決問題更多的問題。 – ACIDSTEALTH

+0

當您遇到錯誤時,請始終添加完整的堆棧跟蹤! – phoet

0

我相信你在這裏濫用包含驗證器。如果你想驗證一個關聯的模型存在,而不是它的id列有一個值,你可以用兩種方法做到這一點。在ActivRecord中,您可以使用presence validator

validates :company, presence: true 

您還應該在數據庫級別使用foreign key constraint。這樣可以防止在關聯表中沒有相應的記錄時保存模型。

add_foreign_key:僱主:公司

如果它得到過去的ActiveRecord,如果沒有公司的記錄與給定company_id數據庫將拋出一個錯誤。

相關問題