Можно ли создать хеш с атрибутами? - PullRequest
1 голос
/ 19 июля 2011

Я хочу иметь возможность взять идентификатор из другой коллекции и использовать его в качестве ключа для хэша.Тогда я хотел бы иметь возможность применять различные атрибуты к каждому.Это будет что-то вроде:

@books = Hash.new

@books[key].title = "A Title"
@books[key].condition = "Poor"
@books[key].rating = "Excellent"

или что-то в этом роде.Возможно ли это даже с некоторыми изменениями?

Спасибо за ваше время!

Редактировать: я должен был добавить, что нежелательно создавать класс в этом случае, хотя я могу в конечном итогесделай это.

Ответы [ 5 ]

3 голосов
/ 19 июля 2011

Если вы хотите именно этот синтаксис, вы можете создать хеш OpenStruct s:

require 'ostruct'
@books = Hash.new { |h, k| h[k] = OpenStruct.new }
key = 1
@books[key].title = "A Title"
@books[key].condition = "Poor"
@books[key].rating = "Excellent"
@books #=> {1=>#<OpenStruct title="A Title", condition="Poor", rating="Excellent">}
2 голосов
/ 19 июля 2011

Вы можете использовать многомерный хэш?

@books = Book.all
@books_hash = {}
@books.each do |book|
  @books_hash[book.id] = {}
  @books_hash[book.id][:title] = book.title
  @books_hash[book.id][:rating] = book.rating
end
1 голос
/ 19 июля 2011

Вы, вероятно, никогда не захотите это делать, а просто ответите на вопрос.

Возможно ли это даже с некоторыми изменениями?

Да, мы можем создать наш собственный класс, чтобы сделать это довольно легко.

class MyAnonObject
  attr_accessor attributes

  def attributes
    @attributes ||= {}
  end

  def method_missing method, *args, &block
    if method =~ /^(\w+)=$/
      @attributes[$1] = args[0]
    else
      @attributes[$1]
    end     
  end
end

И тогда мы можем изменить ваш пример для использования этого нового класса.

@books = Hash.new { MyAnonObject.new }

@books[key].title = "A Title"
@books[key].condition = "Poor"
@books[key].rating = "Excellent"

При этом я бы не рекомендовал это решение. Это может быть очень запутанным, чтобы читать. Однако это возможно =) И действительно, это просто многомерный хеш со странной семантикой.

0 голосов
/ 19 июля 2011

Подобно тому, как умер трижды, но Book.new создается хэшем:

class Book
  attr_accessor :title
  attr_accessor :condition
  attr_accessor :rating
  def initialize()
    @undefined_values = {}
  end
  def method_missing ( m, *args )
    @undefined_values[m] = args
  end
  def inspect()
    "Book #{@title} (#{@condition}, #{@rating}, #{@undefined_values.inspect})"
  end
end  
@books = Hash.new{ |hash,k| hash[k] =  Book.new 
}

key = :xx
@books[key].title = "A Title"
@books[key].condition = "Poor"
@books[key].rating = "Excellent"
@books[key].isbn = "123456"

p @books[key] #-> Book A Title (Poor, Excellent, {:isbn==>["123456"]})

edit: добавлен код для обработки неопределенных значений. p @books [ключ]

0 голосов
/ 19 июля 2011

Вы можете сделать объект типа Book.

class Book
  attr_accessor :tilte, :rating, :condition
end

А затем измените ваш пример, чтобы использовать новый класс Book.

@books = Hash.new

@books[key] = Book.new
@books[key].title = "A Title"
@books[key].condition = "Poor"
@books[key].rating = "Excellent"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...