我的Ruby on Rails 3控制器有一个简单的If Else语句似乎不起作用。
我的发言:
def create
if @trained = Certificate.where(user_id: params[:certificate][:user_id])
@trained.first.update_attributes(attend: "Yes")
else
@trained = Certificate.new(params[:certificate])
if @trained.save
@trained.update_attributes(attend: "Yes")
end
end
redirect_to grandstreamers_resellers_path
end
这是带有错误的日志,'update_attributes'的NoMethodError,但是这行不应该运行,因为它找不到带有user_id'1'的证书。 为什么不做else语句?
Started POST "/certificates" for 50.241.102.234 at 2014-01-06 07:01:55 -0800
Processing by CertificatesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"TM6GPqslIs013O+mOuxGXyyD90T2O5lSZmnqKTFPwVw=", "certificate"=>{"user_id"=>"1"}, "commit"=>"Train"}
Certificate Load (0.1ms) SELECT `certificates`.* FROM `certificates` WHERE `certificates`.`user_id` = 1 LIMIT 1
Completed 500 Internal Server Error in 1ms
NoMethodError (undefined method `update_attributes' for nil:NilClass):
app/controllers/certificates_controller.rb:5:in `create'
答案 0 :(得分:5)
where
子句永远不会返回nil ,它返回一个ActiveRecord :: Relation对象,可以为空!
请改为尝试:
def create
if @trained = Certificate.where(user_id: params[:certificate][:user_id]).first
@trained.update_attributes(attend: "No")
else
@trained = Certificate.new(params[:certificate])
if @trained.save
@trained.update_attributes(attend: "Yes")
end
end
redirect_to grandstreamers_resellers_path
end
但我会将我的代码重构为以下内容:
def create
@trained = Certificate.where(user_id: params[:certificate][:user_id]).first
@trained ||= Certificate.new(params[:certificate])
if @trained.persisted? # tests if the records is persisted in the DB (has an ID)
@trained.attend = "No"
else
@trained.attend = "Yes"
end
@trained.save
redirect_to grandstreamers_resellers_path
end
非常短的版本:
def create
@trained = Certificate.where(user_id: params[:certificate][:user_id]).first || Certificate.new(params[:certificate])
@trained.attend = @trained.persisted? ? "No" : "Yes"
@trained.save
redirect_to grandstreamers_resellers_path
end
对于记录(@NitinJ请看一下),您可以在if条件中指定变量:
if first_user = User.first
# if User.first does not returns nil, executes the first block with local variable first_user available
first_user.id
else
# User.first returned nil
end
答案 1 :(得分:1)
Certificate.where(user_id: params[:certificate][:user_id])
以上语句返回一个从不nil
的关系,因此条件将始终为true
,即使关系为空
如果您期望0或1结果,则可以使用
if @trained = Certificate.where(user_id: params[:certificate][:user_id]).first
#...
如果你期望0或几个结果,你可以使用(不是很优雅):
if (@trained = Certificate.where(user_id: params[:certificate][:user_id]).to_a) && @trained.any?
#...
答案 2 :(得分:0)
如果条件
,您将被分配值@trained = Certificate.where(user_id: params[:certificate][:user_id])
将其更改为
@trained = Certificate.where(user_id: params[:certificate][:user_id])
if @trained.exists?
else
end