Лучший способ сделать атрибут всегда массивом? - PullRequest
3 голосов
/ 12 марта 2010

Я использую свой проект MOO, чтобы научить себя тестировать управляемый дизайн, и он забирает меня в интересные места. Например, я написал тест, в котором говорится, что атрибут определенного объекта всегда должен возвращать массив, поэтому -

t = Thing.new("test")
p t.names  #-> ["test"]

t.names = nil
p t.names #-> []

Код, который у меня есть для этого, в порядке, но он не кажется мне ужасным:

class Thing

   def initialize(names)
      self.names = names
   end

   def names=(n)
      n = [] if n.nil?
      n = [n] unless n.instance_of?(Array)

      @names = n
   end

   attr_reader :names
end

Есть ли более элегантный, рубиновый способ сделать это?
(NB: если кто-то хочет сказать мне, почему писать этот глупый тест, это тоже было бы интересно ...)

Ответы [ 5 ]

5 голосов
/ 12 марта 2010

Я хотел бы отметить, что уже есть встроенный метод, чтобы делать то, что вы хотите! Это называется Array(). Вопрос, который нужно задать себе: что происходит с классами, которые можно преобразовать в массивы (например, 0..42)?

Я чувствую, что большинство Rubyist ожидают, что они будут обращены. Итак:

class Thing
  attr_accessor :names

  def initialize(names)
    self.names = names
  end

  def names=(values)
    @names = Array(values)
  end
end

Вы получите те же результаты, например:

t = Thing.new("car")
t.names  #-> ["car"]

t.names = nil
t.names  #-> []

t.names = 42
t.names  #-> [42]

t.names = [1, 2, 3]
t.names #-> [1, 2, 3]

t.names = 1..3
t.names #-> [1, 2, 3]  # Is this what you want, or not?
3 голосов
/ 12 марта 2010

Попробуйте это:

class Thing

   def initialize(names)
      self.names = names
   end

   def names=(n)
     @names= [*(n||[])]
   end

   attr_reader :names
end

Давайте проверим класс:

t = Thing.new("car")
t.names  #-> ["test"]

t.names = nil
t.names  #-> []

t.names = [1, 2, 3]
t.names #-> [1, 2, 3]
2 голосов
/ 12 марта 2010

Вы можете использовать метод получения для форматирования значения.

class Thing

  def initialize(names)
    self.names = names
  end

  def names
    [*@names].compact
  end

  def names=(values)
    @names = values
  end

end

t = Thing.new("test")
p t.names  #-> ["test"]

t.names = nil
p t.names #-> []
1 голос
/ 12 марта 2010

В другом запахе, как мои предыдущие ответы:


class Thing
  def initialize(*names)                                                                                                                                                                                                                                                      
    @names = names
  end 
  def names
    @names || []
  end 
  def names=(*names)
    @names = names
  end 
end

t = Thing.new("test")
p t.names  #-> ["test"]

t.names = nil 
p t.names #-> []
0 голосов
/ 12 марта 2010

Используйте * для извлечения всех параметров в массиве в вашем методе инициализации


class Thing
   attr_accessor :names

   def initialize(*names)
      @names = names
   end
end

t = Thing.new("test")
p t.names  #-> ["test"]

t.names = nil
p t.names #-> nil

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...