添加模型级别验证是否有意义,例如:
class Person < ApplicationRecord
validates :name, presence: true
end
当它是一个未被路由公开的资源时?
我的一个好朋友告诉我,我应该总是为数据库中不能为空的列添加验证。例如:
class CreatePosts < ActiveRecord::Migration[6.0]
def change
create_table :posts do |t|
t.belongs_to :site, null: false
t.string :title, null: false
t.timestamps
end
end
end
在这种情况下,我应该有以下验证:
class Post < ApplicationRecord
validates :site_id, presence: true
validates :title, presence: true
end
现在,只能通过父级创建帖子:
class Site < ApplicationRecord
accepts_nested_attributes_for :post
# ...
end
但当我尝试通过该站点创建帖子时,它将失败,并显示以下信息:
{
"post.site_id": [
"can't be blank"
]
}
我应该还是不应该添加验证?为不能通过路由直接接触的模型添加验证似乎有点奇怪。
谢谢。
发布于 2019-11-26 13:28:08
当模型没有被路由公开时,为模型添加验证有意义吗?
是。
并不是Rails应用程序中的每个模型实际上都对应于一个路由和它自己的控制器。模型可以表示的不仅仅是RESTful资源(尽管99%的时间都在使用它们。
此外,没有路由并不意味着模型不处理用户输入。当您使用嵌套属性时,您仍然需要从用户获取输入。
但这在这里并不是很重要。
通常,在定义嵌套资源时,您可以这样做:
resources :sites do
resources :posts
end
class PostsController < ApplicationController
before :action_set_site
# POST /sites/1/posts
def create
@post = @site.posts.new(post_params)
# ...
end
private
def set_site
@site = Site.find(params[:site_id])
end
end
在这种情况下,是否在Post上进行验证并不重要,因为如果参数不存在或与记录不对应,Site.find(params[:site_id])
将引发ActiveRecord::RecordNotFound
错误。Rails捕捉到这个异常并返回一个404 - Not Found
响应,这是本例中的正确响应。如果客户端尝试在不存在的终结点上创建资源,则不应返回422 - Bad Entity
。
您似乎完全误解了嵌套属性的用途。如果您必须将多个资源的创建/更新合并到一个表单/请求中,那么accepts_nested_attributes_for
是一种非常有用的技巧。在这种情况下,如果你想让用户同时创建一个帖子和站点。在这种情况下,验证也是无关紧要的,因为设计上的嵌套属性会将帖子嵌套在站点中。
不应该仅仅因为一个资源只能存在于另一个资源的上下文中而使用它。这就是嵌套路由的用途。
发布于 2019-11-26 13:22:20
使用嵌套属性时,保存站点+帖子时site_id
有时是未知的。您必须告诉rails这些关联是相关的,如下所示
class Site
has_many :posts
class Post
belongs_to :site, inverse_of: :posts
请注意,从Rails5开始,添加belongs_to
本身就会添加验证。可以通过以下方式来推翻这一点:
belongs_to :site, optional: true
当使用嵌套属性时,您必须删除validates :site_id, presence: true
验证,因为在检查验证时site_id
是未知的。在保存site + post之前(因此,在分配id之前)检查验证(在rails级别)。
数据库约束绝对是有价值的imho。特别需要/建议在rails级别添加验证,以便在输入表单时(换句话说,如果它们是用用户生成的数据创建/编辑的),以一种更用户友好的方式捕获错误。因此,哪条路由公开它们并不重要,重要的是是否有一个包含表单的页面来创建/编辑它们。
https://stackoverflow.com/questions/59051698
复制