在验证之前进行ActiveModel属性类型转换?

时间:2018-12-21 17:50:18

标签: ruby-on-rails

如何在验证之前 进行属性类型转换?

在此示例中,我希望在delicious验证之前将属性inclusion类型转换为布尔值。

require "bundler/inline"
gemfile(true) do
  ruby "2.4.3"
  source "https://rubygems.org"
  gem "activemodel", "5.2.2"
  gem "actionpack", "5.2.2"
end
require "active_model"
require "action_controller"
require "minitest/autorun"

class Fruit
  include ActiveModel::Model
  include ActiveModel::Attributes
  attr_accessor :delicious, :name
  attribute :delicious, :boolean
  validates :delicious, inclusion: { in: [false, true] }
end

class TestFruit < Minitest::Test
  def test_fruit
    params = ActionController::Parameters.new(
      delicious: '1', # rails checkboxes use strings '0' or '1'
      name: 'banana'
    ).permit!
    banana = Fruit.new(params)
    banana.validate
    assert_equal [], banana.errors.full_messages
    # Fails: ["Delicious is not included in the list"]
  end
end

请注意,这个问题与ActiveRecord无关。

2 个答案:

答案 0 :(得分:3)

使用自定义设置器

    <div class="container">
   <div *ngFor="let t of table; let i = index">
        <div [ngStyle]="{'background-color': t.date > | t:today ? 'red' : 'green'}">
            <ul class="otherStyle">
                <li>{{t.name}}</li>
                <span>{{t.date}}</span>
            </ul>
        </div>
    </div> 
</div>

这样,您将始终拥有一个布尔值(或nil)。

答案 1 :(得分:1)

?

删除attr_accessor :deliciousattribute将定义getter和setter方法。

一些分析:

attr_accessor

字母和设置者直接在Fruit上定义。

1| class Fruit
2|   attr_accessor :delicious
3| end

method = Fruit.new.method(:delicious)
method.owner # => Fruit
method.source_location # => ['/path/to/fruit.rb', 2]

attribute

字母和设置器是在Fruit用于方法查找的匿名模块实例上定义的。

1| class Fruit
2|  attribute :delicious
3| end

method = Fruit.new.method(:delicious)
mod = method.owner # => #<Module:0x00007fc583da1f60>
Fruit.ancestors.include?(mod) # => true
method.source_location # => ['/path/to/active_model/attribute_methods.rb', 36]

同时使用attr_accessorattribute时,Fruit将调用更直接的getter和setter:由attr_accessor定义的getter和setter。

1| class Fruit
2|   attr_accessor :delicious
3|   attribute :delicious
4| end

method = Fruit.new.method(:delicious)
method.owner # => Fruit
method.source_location # => ['/path/to/fruit.rb', 2]