阅读&写一个属性,默认值和验证

时间:2018-06-18 00:10:21

标签: ruby

我正在构建一个类来表示自动生成的玩家角色。角色具有性别,可接受的值为:male:female。我需要一个属性读取器和编写器来允许访问和自定义,但也需要一个"默认"如果尚未选择值且用户不想选择一个值,则返回值。我有以下代码:

class Character
    attr :gender

    def gender= g
        g = nil unless g == :male or g == :female
        @gender = g || [:male, :female].sample
    end

    def gender
        @gender ||= gender=(nil)
    end
end

我们的想法是始终通过setter来确保值是有效的,并且在我决定将新值添加到性别列表中时,使代码更易于维护。我面临的问题是:a)验证行具有冗余值,其下方的设置行(在gender =方法中)和b)从阅读器方法调用writer方法看起来非常奇怪&#34 ;零"通过。有什么想法让这更优雅吗?

3 个答案:

答案 0 :(得分:3)

如果在构造函数中设置了有效值,则在getter中不需要setter。将来,如果要添加新的性别,可以将现有字符更新为一次性内容。这可以使您的代码更清晰。

class Character
    attr :gender

    def initialize
       @gender = valid_genders.sample
    end

    def gender= g
       @gender = g if valid_genders.include? g
    end

    private

    def valid_genders
      [:male, :female]
    end

end

答案 1 :(得分:1)

真的天真,也许是矫枉过正。如果您真的认真地以干净时尚的方式做到这一点,并且计划不仅仅具有性别属性,那么您可能希望投资类似......

skip

这几乎就是module CoolAttributes def self.included(base) base.extend ClassMethods end module ClassMethods def attribute(name, type, options = {}) get(name, type, options) set(name, type, options) end def get(name, type, options) define_method(name) do instance_variable_get(:"@#{name}") || if options[:default].is_a?(Proc) options[:default].call else options[:default] end end end def set(name, type, options) define_method("#{name}=") do |value| instance_variable_set(:"@#{name}", self.class.cast_to(type, value)) end end def cast_to(type, value) if type == :boolean if ['false', 0, '0', false].include?(value) false else true end elsif type == :symbol value.to_s.to_sym end end end end class Character include CoolAttributes attribute :gender, :symbol, :default => :male end c = Character.new puts c.gender # male c.gender = 'male' puts c.gender.class # Symbol

编辑:我最终制作了一个宝石。 https://github.com/joshmn/attributary

答案 2 :(得分:0)

我的版本,您也可以随意初始化:

pred1