我需要在create方法之前验证字段
在我的_form.html.erb中我有两个模型,一个是所有者模型,另一个是我创建的模型以获得其他参数,我需要在进入create方法之前验证这些参数,我可以使用如果,但这不是最好的做法。
def create
@customer = Customer.new(customer_params)
#read the city name, since this is requested by city name (string) and it shoud be "id" in the system
city = city_params()
@customer.city_id = City.find_by(name: city["name"]).id
respond_to do |format|
if @customer.save
format.html { redirect_to @customer, notice: 'Customer was successfully created.' }
format.json { render action: 'show', status: :created, location: @customer }
else
format.html { render action: 'new' }
format.json { render json: @customer.errors, status: :unprocessable_entity }
end
end
end
我需要验证城市名称,因为客户所有者必须拥有city_id,并且_form请求名称(字符串),所以我需要找到城市,但之前我需要验证城市名称是否有值它存在,
如何在模型中验证?
答案 0 :(得分:1)
如果我是你,我会首先将所有这些逻辑保留在控制器中并使用过滤器来查找城市:
class CustomersController < ApplicationController
before_action :find_city, only: [:create, :update]
def create
@customer = Customer.new(customer_params)
#read the city name, since this is requested by city name (string) and it shoud be "id" in the system
@customer.city_id = @city.try(:id) # This returns `nil` if the city was not found
respond_to do |format|
if @customer.save
format.html { redirect_to @customer, notice: 'Customer was successfully created.' }
format.json { render action: 'show', status: :created, location: @customer }
else
format.html { render action: 'new' }
format.json { render json: @customer.errors, status: :unprocessable_entity }
end
end
end
private
def find_city
@city = City.find_by(name: params[:city][:name]) # No need for strong parameters for this
end
end
然后确保您在city_id
课程中验证Customer
的存在:
class Customer < ActiveRecord::Base
validates :city_id, presence: true
end
稍后,如果您发现需要从控制器中提取此逻辑,请考虑创建service object或form object。因为这是一个简单的案例(只涉及2个类),我现在暂时不会创建这些构造。控制器层足以处理这个简单的逻辑。
为什么不直接将逻辑移到模型中?我可以从经验中告诉你,你不想用大量涉及其他模型类的逻辑搞乱你的模型。在我看来,Customer
对City
不太了解。
答案 1 :(得分:0)
<强> before_validate 强>
你可能在你的模型中使用before_validate
回调:
#app/models/customer.rb
Class Customer < ActiveRecord::Base
attr_accessor :city_name
before_validate :set_city
private
def set_city
city_id = City.find_by(name: city_name).id
end
end
-
自定义验证方法
我认为最重要的是你最好使用自定义验证方法。您基本上希望将用户返回到表单,并显示错误消息&#34; City not found&#34;或类似的;这完全在custom validation method的范围内:
#app/models/customer.rb
Class Customer < ActiveRecord::Base
validate :check_city_id
private
def check_city_id
errors.add(:city_id, "City doesn't exist") unless City.try city_id
end
end
-
<强>系统强>
这种问题可以通过简单地给用户选择输入中的id
来处理;而不是通过name
选择:
#app/views/customers/new.html.erb
<%= form_for @customer do |f| %>
<%= f.select :city_id, City.all.collect {|p| [ p.name, p.id ] } %>
<% end %>
我认为您的方法是让用户能够选择城市name
,然后在后端进行验证是非常低效的;同时为用户提供一套严格的选项,以便按城市选择买家更为健全
答案 2 :(得分:-1)
我们有一些名为callbacks http://api.rubyonrails.org/classes/AbstractController/Callbacks/ClassMethods.html
的东西..使用这个我们可以在模型中触发我们所需的验证。
您可以创建自己的验证逻辑,例如
before_create :method_name
def method_name
your logic.....example: validates :city_name ..
end