Rails 5.1.4验证:如何接受空白属性但不保存到数据库?
嗨,作为Rails新手遇到这种问题很正常,我来帮你一步步解决!你的需求是允许用户提交空白输入,但不把空值保存到数据库,同时确保最终至少有2个有效的选项对吧?结合你的代码,我们可以从这几个方面调整:
1. 用
accepts_nested_attributes_for自动过滤空白选项 在你的Voting模型里,给accepts_nested_attributes_for加上reject_if选项,这样Rails会自动跳过那些vote字段为空的选项,不会创建对应的数据库记录:
class Voting < ApplicationRecord has_many :options # 自动拒绝vote为空的选项属性,不生成对应的记录 accepts_nested_attributes_for :options, reject_if: proc { |attrs| attrs['vote'].blank? } validates :content, presence: true end
2. 调整验证逻辑,确保至少有2个有效选项
你之前在Option模型里的验证逻辑有点绕,应该把“至少2个选项”的验证放在Voting模型里——毕竟这是投票本身的要求,不是单个选项的:
class Voting < ApplicationRecord has_many :options accepts_nested_attributes_for :options, reject_if: proc { |attrs| attrs['vote'].blank? } validates :content, presence: true # 过滤空白选项后,验证有效选项数量至少为2 validates :options, length: { minimum: 2, message: "at least two Options required." } end
然后把Option模型里多余的验证删掉:
class Option < ApplicationRecord belongs_to :voting validates_associated :voting # 移除之前的validates :vote相关代码 end
3. 优化表单和参数处理(符合Rails规范)
你的当前表单参数格式不太适配Rails嵌套属性的逻辑,我们调整视图让表单自动生成正确的参数结构:
# votings/show.html.erb <strong>Your Voting:</strong> <p><%= @voting.content %></p> <% if @voting.errors.any? %> <div> <% @voting.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </div> <% end %> <ul> <%= form_with(model: @voting, local: true) do |form| %> <p> <%= form.label :vote %><br> <% 3.times do %> <%# 使用fields_for生成嵌套属性的输入框,自动适配参数格式 %> <%= form.fields_for :options, @voting.options.build do |option_form| %> <%= option_form.text_field :vote %><br><br> <% end %> <% end %> </p> <p> <%= form.submit %> </p> <% end %> </ul>
接着调整控制器的create方法和参数过滤,让Rails自动处理嵌套属性:
class OptionsController < ApplicationController def index @voting = Voting.find(params[:voting_id]) @options = @voting.options end def create @voting = Voting.find(params[:voting_id]) # 直接用update处理嵌套属性,自动创建有效选项 if @voting.update(option_params) flash[:notice] = "Options added successfully!" redirect_to voting_options_path(@voting) else render 'votings/show' end end private def option_params # 允许voting的options_attributes参数,只包含vote字段 params.require(:voting).permit(options_attributes: [:vote]) end end
为什么这样做?
reject_if会帮你自动过滤所有空白选项,既不会把空值存入数据库,也不会触发不必要的验证错误;- 把“至少2个选项”的验证放在
Voting模型里,逻辑更清晰,而且会在过滤空白选项后检查有效选项的数量,确保最终数据库里的选项都是非空的; - 用Rails标准的嵌套属性表单和参数处理,代码更简洁,也符合Rails的最佳实践。
内容的提问来源于stack exchange,提问作者Fly
相关产品推荐
相关产品推荐

