我想要一個User
模型創建/驗證/更新具有以下屬性的系統:Rails&ActiveRecord - 對於on::create和on :: update的不同驗證?
要求1
當User
首次創建時,:name
,:email
和:password
屬性都應該存在否則創建保存應該失敗。
要求2
當User
被更新,這三個屬性可以單獨更新,所以更新保存可以繼續,如果其中一個或兩個是空白的。
簡單,普通的要求對嗎?我不確定。最明顯的方式,以滿足第一個要求是在User
模型validations
與presence: true
所有三個:
user.rb
validates :name, length: {maximum: 50}, presence: true
validates :email, uniqueness: {case_sensitive: false}, presence: true
validates :password, length: {minimum: 6}, presence: true
從這裏
那麼,我們如何滿足第二個要求?
嘗試1
添加on: :create
的驗證:
validates :name, length: {maximum: 50}, presence: true, on: :create
validates :email, uniqueness: {case_sensitive: false}, presence: true, on: :create
validates :password, length: {minimum: 6}, presence: true, on: :create
這是災難性的。如果用戶試圖通過用新name
但空白email
和password
領域,name
的確會被更新,但email
和password
屬性也將更新爲空值提交更新的形式來更新只是他name
- ""
- 因爲驗證將不會運行。
嘗試2
添加allow_nil: true
的驗證:
validates :name, length: {maximum: 50}, presence: true, allow_nil: true
validates :email, uniqueness: {case_sensitive: false}, presence: true, allow_nil: true
validates :password, length: {minimum: 6}, presence: true, allow_nil: true
同樣是災難性的。您可以使用空白屬性創建和更新用戶。
嘗試3
只有驗證,如果它是一個新的記錄或字段不爲空:
validates :email, uniqueness: {case_sensitive: false}, presence: true, if: :should_validate?
def should_validate?
new_record? || email.present?
end
這已被接受爲別處#2正確的解決方案,但如果我指正錯了,是不是也是災難性的?如果您使用空白email
字段更新模型,should_validate?
將返回false
,則電子郵件驗證將不會運行,並且數據庫將更新爲空白email
。
請糾正我,如果我錯了,但這個「解決方案」將工作如果沒有驗證也意味着不更新,但事實並非如此呢?如果你不運行驗證,該屬性仍然會保存到數據庫中嗎?
嘗試4
在控制器中,從除去了params
屬性,如果它是空白:
user.rb
validates :name, length: {maximum: 50}, presence: true
validates :email, uniqueness: {case_sensitive: false}, presence: true
validates :password, length: {minimum: 6}, presence: true
users_controller.rb
def update
params[:user].delete(:name) if params[:user][:name].blank?
params[:user].delete(:email) if params[:user][:email].blank?
params[:user].delete(:password) if params[:user][:password].blank?
if @user.update_attributes(update_user_params)
flash[:success] = "Edit Successful."
redirect_to @user
else
@title = "Edit user"
render 'edit'
end
end
def update_user_params
params.require(:user).permit(:name, :email, :password)
end
由於驗證中的presence: true
,這不起作用。如果params
中沒有任何屬性,驗證將失敗,並且記錄不會更新。
同樣,這已被接受爲Stackoverflow其他地方的正確解決方案,所以我很確定我在某處丟失了某些東西,請告訴我在哪裏?
嘗試5
從params
刪除屬性,如果是空白的,並從驗證刪除presence: true
:
user.rb
validates :name, length: {maximum: 50}
validates :email, uniqueness: {case_sensitive: false}
validates :password, length: {minimum: 6}
users_controller.rb
def update
params[:user].delete(:name) if params[:user][:name].blank?
params[:user].delete(:email) if params[:user][:email].blank?
params[:user].delete(:password) if params[:user][:password].blank?
if @user.update_attributes(update_user_params)
flash[:success] = "Edit Successful."
redirect_to @user
else
@title = "Edit user"
render 'edit'
end
end
這不起作用。我們已經達到了要求2,但銷燬了要求1.使用此「解決方案」,您確實可以更新記錄的個別屬性,但您也可以使用空白屬性創建新記錄。
嘗試6
唯一可能的解決方案,我可以看到的是,以具有不同的驗證爲on: :create
和on: :update
。如果您要創建記錄,則堅持要求presence: true
,但如果要更新記錄,請刪除presence: true
。您還需要在控制器中的空屬性去除:
user.rb
validates :name, length: {maximum: 50}, presence: true, on: :create
validates :email, uniqueness: {case_sensitive: false}, presence: true, on: :create
validates :password, length: {minimum: 6}, presence: true, on: :create
validates :name, length: {maximum: 50}, on: :update
validates :email, uniqueness: {case_sensitive: false}, on: :update
validates :password, length: {minimum: 6}, on: :update
users_controller.rb
def update
params[:user].delete(:name) if params[:user][:name].blank?
params[:user].delete(:email) if params[:user][:email].blank?
params[:user].delete(:password) if params[:user][:password].blank?
if @user.update_attributes(update_user_params)
flash[:success] = "Edit Successful."
redirect_to @user
else
@title = "Edit user"
render 'edit'
end
end
這是允許的?它會工作嗎?我完全錯過了解決這個問題的正確方法嗎?
待辦事項你想保存名稱,電子郵件爲零更新?我認爲沒有必要單獨更新名稱和電子郵件。您只需在名稱或電子郵件地址等字段中進行更改,不要讓其他提交的空白變得簡單。 –
絕對不是。姓名和電子郵件永遠不應更新爲零。 – Bazley
剛剛發佈的解決方案看看 –