开发者

Is it possible to create a hash with attributes?

I want to be able to take the id from another collection, and use that as the key for a hash. Then I would like to be able to apply various attributes to each. It would be something like:

@books = Hash.new

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

or something to that effect. Is this even possible with some tweaks?

Thanks for your time!

Edit: I should have added that it is undesirable to create a Class in this case, although I ma开发者_开发问答y end up having to do that.


If you want exactly that syntax you can create a hash of OpenStructs:

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">}


You can use multidimensional Hash?

@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


You probably never want to do this, but just to answer the question.

Is this even possible with some tweaks?

Yes, we can create our own class to do this pretty easily.

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

And then we can modify your example to use this new class.

@books = Hash.new { MyAnonObject.new }

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

That being said, I wouldn't recommend this solution. It can be very confusing to read. However, it is possible =) And really, this is just a multi-dimensional hash with strange semantics.


You can make an object of type Book.

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

And then modify your example to use the new Book class.

@books = Hash.new

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


Similar to diedthreetimes anser, but the Book.new is done by the Hash:

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: Added code to handle undefined values. p @books[key]

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜