Ruby:自定义实现属性访问器并进行验证

时间:2015-05-04 11:16:13

标签: ruby-on-rails ruby

我正在尝试实施javax.sql.rowset.serial.SerialBlob

让我们说custom attribute accessors with validation。现在这个attr_validated

1:应该使用与attr_accessor相同的setter和getter方法。 ## 此部分已完成

2:它应该验证给定的块。

attr_validated

这个问题可能看起来像任何其他问题,但事实并非如此。 谷歌搜索时我得到了

  

1: Ist Part

attr_validated :num_legs do |v|
v <= 4
end
  

2:我们如何实施第二部分

任何帮助将不胜感激!!!

2 个答案:

答案 0 :(得分:4)

这样的事情怎么样:

class Class
  def attr_validated(*args, &validator)
    args.each do |name|
      define_method("#{name}=") do |value|
        if block_given?
          raise ArgumentError, "Value '#{value}' is invalid" unless validator.call(value)
        end

        instance_variable_set("@#{name}", value)
      end

      define_method(name) do
        instance_variable_get("@#{name}")
      end
    end
  end
end

class Person
  attr_validated(:name, :occupation) { |name| name.length > 3 }
end

p1 = Person.new
p1.name = "John The Tester"
p1.occupation = "Software developer"
p "#{p1.name} - #{p1.occupation}"

p2 = Person.new
p2.name = "test"
p2.occupation = "Tester"
p "#{p2.name} - #{p2.occupation}"

哪个会产生如下输出:

"John The Tester - Software developer"
app.rb:6:in `block (2 levels) in attr_validated': Value 'test' is invalid (ArgumentError)
        from app.rb:28:in `<main>'

希望有所帮助!

祝你好运!

<强>更新

您可以添加另一个方法,对第一个参数应用验证,如下所示:

class Class
  def attr_validated_first(*args, &validator)
    args.each_with_index do |name, index|
      define_method("#{name}=") do |value|
        if block_given? && index == 0
          raise ArgumentError, "Value '#{value}' is invalid" unless validator.call(value)
        end

        instance_variable_set("@#{name}", value)
      end

      define_method(name) do
        instance_variable_get("@#{name}")
      end
    end
  end
end

但是我不推荐这种方法,这会令人困惑!如果你想用不同的验证规则注册几个属性......你可以多次使用第一个例子中的attr_validated,如下所示:

class Person
  attr_validated(:name)       { |name| name.length > 3 }
  attr_validated(:occupation) { |occupation| occupation == "Ruby Developer" }
end

答案 1 :(得分:3)

这很容易。如果块表示参数无效,则只需raise ArgumentError设置器中的class Person attr_reader :name def name=(name) raise ArgumentError, "'#{name}' is not a valid name!" if rejector.(name) @name = name end private attr_accessor :rejector def initialize(&rejector) self.rejector = rejector end end artist = Person.new do |person| person.length > 6 end artist.name = 'The Artist Formerly Known As Prince' # ArgumentError: 'The Artist Formerly Known As Prince' is not a valid name! artist.name = 'ruby' # => 'ruby'

MAX(If(subjects.name="Chemistry",marks.marks,'')) Chemistry,
MAX(If(subjects.name="Physics",marks.marks,'')) Physics,
.....