Ruby on rails 在创建之前验证关联的对象是否存在
我一直在学习Ruby on rails 在创建之前验证关联的对象是否存在,ruby-on-rails,validation,Ruby On Rails,Validation,我一直在学习入门rails教程,现在正在尝试一些自定义功能 我有两种型号,Person和Hangout。一个人可以有许多闲逛场所。在创建Hangout时,必须选择Person并将其与新的Hangout关联。然而,当我调用我的create操作时,我遇到了一些问题。这将在人员的验证存在之前触发 我走错方向了吗?似乎我不应该在创建验证之前创建自定义的,以确保使用人员创建了Hangout #hangout_controller def create @person = Person.find(par
入门
rails教程,现在正在尝试一些自定义功能
我有两种型号,Person
和Hangout
。一个人
可以有许多闲逛场所
。在创建Hangout
时,必须选择Person
并将其与新的Hangout
关联。然而,当我调用我的create
操作时,我遇到了一些问题。这将在人员的验证存在之前触发
我走错方向了吗?似乎我不应该在创建
验证之前创建自定义的,以确保使用人员
创建了Hangout
#hangout_controller
def create
@person = Person.find(params[:hangout][:person_id])
@hangout = @person.hangouts.create(hangout_params)
@hangout.save
redirect_to hangouts_path(@hangout)
end
#hangout.rb
class Hangout < ActiveRecord::Base
belongs_to :person
validates_presence_of :person
end
#person.rb
class Person < ActiveRecord::Base
has_many :hangouts
validates :first_name, presence: true
validates :met_location, presence: true
validates :last_contacted, presence: true
def full_name
"#{first_name} #{last_name}"
end
end
#挂断#控制器
def创建
@person=person.find(参数[:hangout][:person\u id])
@hangout=@person.hangouts.create(hangout\u参数)
@出去玩,救命
重定向到hangout路径(@hangout)
结束
#hangout.rb
类挂起
您对控制器和模型责任感到困惑
让我试着解释一下我认为让你困惑的是什么:
首先,在您的电脑中尝试以下操作:
它不应该允许您这样做,因为您没有将Person
对象传递给create
方法。因此,我们确认验证工作正常。该验证意味着在创建Hangout
之前,确保存在person
属性。所有这些都是模型级的,还没有关于控制器的内容
让我们转到控制器部分。当控制器的创建操作“被激发”时,该控制器根本不知道您要做什么。它不运行任何验证。这只是一个操作,如果您愿意,可以调用Hangout
模型来创建其中一个
我相信当你说“it fires”时,你是说HangoutController
的create
操作首先被调用,而不是Hangout
模型上的create
方法。这是完全好的。验证在模型级别运行
在验证人员的存在之前创建操作激发
我认为您对rails MVC感到困惑。表单包含url,当您提交表单时,表单参数将根据您在routes中定义的路由发送到控制器操作。rb控制器操作,在本例中为创建操作,与模型交互这是非常重要的,它会检查您的验证,如果所有验证都通过,您的对象将保存在数据库中因此,即使在您的应用程序中,控件首先传递给控制器,但如果所有验证都通过,您的对象只保存一次
现在让我们回到您的代码。有几件事你做错了
a您不需要单独关联您的联系人:
在创建操作中,有以下行:
@person = Person.find(params[:hangout][:person_id])
您不需要这样做,因为您的person_id已经来自您的表单,它会自动将您的闲逛与person关联
b您正在调用create方法而不是build:
当您调用方法时,它会为您做两件事:首先初始化您的对象,在您的情况下是您的挂起,如果所有验证都通过,它会保存它。如果没有通过所有验证,只需回滚查询即可
如果您要使用它,它只会使用表单中的参数初始化对象
c验证错误不会显示:
如上所述,由于您调用的是create方法而不是build,因此不会显示验证错误
修复
您的创建方法应如下所示:
def create
@hangout = Hangout.new(hangout_params) # since your person_id is coming from form it'll automatically associate your new hangout with person
if @hangout.save
redirect_to hangouts_path(@hangout)
else
render "new" # this will show up validation errors in your form if your hangout is not saved in database
end
end
private
def hangout_params
params.require(:hangout).permit(:person_id, :other_attributes)
end
嵌套属性
我认为您可以更好地使用-我们已经通过对嵌套模型使用验证实现了您之前所寻求的功能(尽管您可以使用reject_if::all_blank来避免):
虽然我没有测试过以上内容,但我相信这是您应该处理它的方式。这将基本上为特定的人员保存挂起
关联对象-如果挂起
关联对象为空,则允许您拒绝
意见如下:
#app/views/hangouts/new.html.erb
<%= form_for [@person, @hangout] do |f| %>
<%= f.fields_for :hangouts do |h| %>
<%= h.text_field :name %>
<% end %>
<%= f.submit %>
<% end %>
#app/views/hangouts/new.html.erb
您会说:“但是,当我调用我的创建操作时,我遇到了问题。这会在验证for person的存在之前触发。”。什么火?
#app/models/person.rb
Class Person < ActiveRecord::Base
has_many :hangouts
accepts_nested_attributes_for :hangouts, reject_if: :all_blank
end
#app/models/hangout.rb
Class Hangout < ActiveRecord::Base
belongs_to :person
end
#config/routes.rb
resources :people do
resources :hangouts # -> domain.com/people/:people_id/hangouts/new
end
#app/controllers/hangouts_controller.rb
Class HangoutsController < ApplicationController
def new
@person = Person.find params[:people_id]
@hangout = @person.hangouts.build
end
def create
@person = Person.find params[:people_id]
@person.update(hangout_attributes)
end
private
def hangout_attributes
params.require(:person).permit(hangouts_attributes: [:hangout, :attributes])
end
end
#app/views/hangouts/new.html.erb
<%= form_for [@person, @hangout] do |f| %>
<%= f.fields_for :hangouts do |h| %>
<%= h.text_field :name %>
<% end %>
<%= f.submit %>
<% end %>