在Rails中是否可能要求多个强参数?

6

我正在尝试为Rails表单执行一些服务器端验证,我希望要求特定字段具有值。以下是我的控制器中的参数:

private
def post_params
  params.require(:post).permit(:title, :text, :slug)
end

问题在于服务器只是允许这些参数 - 它并不需要它们,因此有可能提交一个完全空白的表单。
据我了解,params.require 只接受一个参数,我尝试绕过这个问题,但没有成功。
private
def post_params
  params.require(:post, :title, :text, :slug)
end
# => wrong number of arguments (4 for 1)

private
def post_params
  all_params = [:post, :title, :text, :slug]
  params.require(all_params)
end
# => param is missing or the value is empty: [:post, :title, :text, :slug]

private
def post_params
  params.require(:post).require(:title).require(:text).require(:slug)
end
# => private method `require' called for "test thing":String

有没有一种方法可以要求多个强参数?


我无法理解你的观点。如果你在至少一个这些属性上使用了验证(例如存在性验证),则甚至不能提交具有空白值的表单。 - Pavan
这对我来说似乎是一个 X-Y 问题。在您的模型验证中使用 presence: true 子句有什么问题吗?我没有任何接受空表单的模型,但我从未修改我的 strong params 来要求超过一个对象... - MarsAtomic
@MarsAtomic 哎呀,看来我之前的做法是错的。我忘记了模型验证,所以我一直在尝试要求参数。我添加了验证,现在一切都好了。谢谢! - Ian Valentine
2个回答

11

强参数用于批量赋值。批量赋值的意思是当您提交表单时,多个值被提交,即模型的多个属性,因此您需要将它们添加到 params.require(:post).permit 中。您看到了单词permit,这意味着这些属性被允许进行批量赋值。现在假设您正在控制器中编写以下内容:

def post_params
  params.require(:post).permit(:title, :text, :slug)
end

并且在您的参数中假设您有:

{"post"=>{"title"=>'Test',"text"=>"Text test","slug"=>"any random name","type"=>"article"}}

现在如果你这样做:

@post = Post.new(post_params)
@post.save

因为您没有将type参数列入白名单,所以会出现未经许可的参数:type。出于安全原因,这是为了仅允许用户从视图更新需要更新的属性。自Rails 4开始引入了Strong Parameters(强参数)。

现在,您需要在模型中要求用户填写这些参数,像这样:

class Post < ActiveRecord::Base
  validates_presence_of :title, :text, :slug
end

这是一个验证,可以强制用户必须输入标题、正文和slug。还有更多类型的验证和一些自定义验证,可以根据需求编写。

更多信息:

Strong Parameters

Validations

希望这可以帮到你。


刚刚想出来了。非常感谢! - Ian Valentine
1
如果我没记错的话,他是在问如何添加多个 strong parameters,而不是解释 strong params 的概念。 - rails_has_elegance
1
如果我没错的话,OP没有理解strong params的用法,他把验证和strong params混淆了,这就是为什么我加入了strong params的解释。如果你觉得不正确,请继续发布正确的答案。 - Deepesh
你的回答非常有用,因为它提示我们不应该使用param.require进行验证,而是应该在模型中使用validates_presence_of或presence: true来完成,但我觉得它并没有解决Rails中params.require概念相当混乱的问题,因为它只接受一个参数。是的,在你的例子中,属性被嵌套在post参数中,但是每当你的参数是平面的而不是嵌套的,并且你想要多个参数时,Rails的strong params概念就会变得无用。 - rails_has_elegance

2

强参数不能用于验证属性的存在,也不应该这样使用。正如@Deep所说,您需要使用“validate presence”来实现这一点。

学术问题在于如何要求多个强参数,“params”一词在这里是误导性的,因为“require”部分指定了属性哈希的键。之所以只接受一个参数,是因为通常表单会提交一个表示单个对象的属性哈希 - 嵌套除外。

然而,从理论上讲,如果您的params哈希包含以下键/值对:

... this: { name: 'this', number: 1 }, that: { color: 'red', size: 'big'} ...

如果您希望分别对这两个属性进行要求和允许,您可以这样做:

def this_and_that_params
  { this: params.require(:this).permit(:name), that: params.require(:that).permit(:color) }
end

这将返回:

... this: { name: 'this' }, that: { color: 'red' } ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接