ruby-on-rails – Rails 4.1枚举引发错误而不是将对象设置为无效

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – Rails 4.1枚举引发错误而不是将对象设置为无效前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用Rails 4.1枚举字段
class User
    enum category: [ :client,:seller,:provider ]
end

用户注册时,他从选择框中选择他的类别.默认为空,因为我想强制用户选择一个选项.

如果用户没有选择任何选项,我想返回带有验证消息的表单.这是注册表单中的选择框代码

<%= f.select :category,[],{},class: "form-control" do  %>
        <option value="99">Choose an option</option>

        <% User.categories.each do |cat,code| %>
            <option value="<%= code %>" <% if params["user"] && code.to_s == params["user"]["category"] %>selected='selected'<%end%> ><%= t(cat) %></option>
        <% end %>
    <% end %>

当控制器创建用户时,它不会向记录添加验证错误,而是引发异常.怎么避免这个?

ArgumentError - '99' is not a valid category:
  (gem) activerecord-4.1.1/lib/active_record/enum.rb:103:in `block (3 levels) in enum'
  (gem) activerecord-4.1.1/lib/active_record/attribute_assignment.rb:45:in `_assign_attribute'
  (gem) activerecord-4.1.1/lib/active_record/attribute_assignment.rb:32:in `block in assign_attributes

解决方法

我真的不喜欢上面列出的问题所说的推理.由于值是通过线路传递的,因此应将其视为自由文本输入,其中期望是在模型中而不是控制器中进行验证.在API中尤其如此,开发人员对表单数据(例如)的预期输入的评价甚至更低.

如果有人想要黑客,这就是我想出来的.通过基本测试,但如果有人发现问题,他会喜欢反馈:

class User
  enum category: [ :client,:provider ]

  def category=(val)
    super val
  rescue
    @__bad_cat_val = val
    super nil
  end
end

这会将类别重置为nil,然后我们可以验证该字段:

class User
...
  validates :category,presence: true
end

问题是我们真的想要验证包含,而不仅仅是存在.为了解决这个问题,我们必须捕获输入(例如,如def category =中所示).然后我们可以使用该值输出我们的消息:

class User
...
  validates :category,inclusion: { 
    in: categories.keys,message: ->(record,error) {
      val = record.instance_variable_get(:@__bad_cat_val)
      return "Category is required" if val.nil?
      "#{val.inspect} is not a valid category"
    }
  }
end

这将为我们提供存在和包容的信息.如果你需要更多地微调它,你将不得不使用自定义验证器(我相信).

猜你在找的Ruby相关文章