From d823f587d19092699cf83e32760c7cc57a4c1b1c Mon Sep 17 00:00:00 2001 From: usa Date: Sat, 25 Mar 2017 18:35:09 +0000 Subject: merge revision(s) 57887: [Backport #13159] lib/ostruct.rb: [DOC] revise docs for OpenStruct * update paragraph on implementation: define_singleton_method is used, not define_method * add call-seq with return values for each_pair * adopt description of dig from Array and Hash * fix description of the hash method * :nodoc: initialize_copy, respond_to_missing? * other small improvements, e.g. use the term `attribute' in the docs (instead of `member'), which is clearer for users of the class * improve code examples: e.g. use more consistent style (always use double quotes, drop `p' and `puts', ...), update inspect output, use example data that is not prone to change (like population) * add more code examples * fix some small errors and grammar [ruby-core:79265] [Bug #13159] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_2@58124 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- lib/ostruct.rb | 151 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 90 insertions(+), 61 deletions(-) (limited to 'lib') diff --git a/lib/ostruct.rb b/lib/ostruct.rb index 3a1cde4322..c44f102547 100644 --- a/lib/ostruct.rb +++ b/lib/ostruct.rb @@ -14,56 +14,58 @@ # accomplished by using Ruby's metaprogramming to define methods on the class # itself. # -# == Examples: +# == Examples # -# require 'ostruct' +# require "ostruct" # # person = OpenStruct.new -# person.name = "John Smith" -# person.age = 70 -# person.pension = 300 +# person.name = "John Smith" +# person.age = 70 # -# puts person.name # -> "John Smith" -# puts person.age # -> 70 -# puts person.address # -> nil +# person.name # => "John Smith" +# person.age # => 70 +# person.address # => nil # -# An OpenStruct employs a Hash internally to store the methods and values and -# can even be initialized with one: +# An OpenStruct employs a Hash internally to store the attributes and values +# and can even be initialized with one: # -# australia = OpenStruct.new(:country => "Australia", :population => 20_000_000) -# p australia # -> +# australia = OpenStruct.new(:country => "Australia", :capital => "Canberra") +# # => # # -# Hash keys with spaces or characters that would normally not be able to use for -# method calls (e.g. ()[]*) will not be immediately available on the -# OpenStruct object as a method for retrieval or assignment, but can be still be -# reached through the Object#send method. +# Hash keys with spaces or characters that could normally not be used for +# method calls (e.g. ()[]*) will not be immediately available +# on the OpenStruct object as a method for retrieval or assignment, but can +# still be reached through the Object#send method. # # measurements = OpenStruct.new("length (in inches)" => 24) -# measurements.send("length (in inches)") # -> 24 +# measurements.send("length (in inches)") # => 24 # -# data_point = OpenStruct.new(:queued? => true) -# data_point.queued? # -> true -# data_point.send("queued?=",false) -# data_point.queued? # -> false +# message = OpenStruct.new(:queued? => true) +# message.queued? # => true +# message.send("queued?=", false) +# message.queued? # => false # -# Removing the presence of a method requires the execution the delete_field -# method as setting the property value to +nil+ will not remove the method. +# Removing the presence of an attribute requires the execution of the +# delete_field method as setting the property value to +nil+ will not +# remove the attribute. # -# first_pet = OpenStruct.new(:name => 'Rowdy', :owner => 'John Smith') -# first_pet.owner = nil -# second_pet = OpenStruct.new(:name => 'Rowdy') +# first_pet = OpenStruct.new(:name => "Rowdy", :owner => "John Smith") +# second_pet = OpenStruct.new(:name => "Rowdy") # -# first_pet == second_pet # -> false +# first_pet.owner = nil +# first_pet # => # +# first_pet == second_pet # => false # # first_pet.delete_field(:owner) -# first_pet == second_pet # -> true +# first_pet # => # +# first_pet == second_pet # => true # # -# == Implementation: +# == Implementation # # An OpenStruct utilizes Ruby's method lookup structure to find and define the -# necessary methods for properties. This is accomplished through the method -# method_missing and define_method. +# necessary methods for properties. This is accomplished through the methods +# method_missing and define_singleton_method. # # This should be a consideration if there is a concern about the performance of # the objects that are created, as there is much more overhead in the setting @@ -78,11 +80,11 @@ class OpenStruct # (can be a Hash, an OpenStruct or a Struct). # For example: # - # require 'ostruct' - # hash = { "country" => "Australia", :population => 20_000_000 } + # require "ostruct" + # hash = { "country" => "Australia", :capital => "Canberra" } # data = OpenStruct.new(hash) # - # p data # -> + # data # => # # def initialize(hash=nil) @table = {} @@ -95,8 +97,8 @@ class OpenStruct end end - # Duplicate an OpenStruct object members. - def initialize_copy(orig) + # Duplicates an OpenStruct object's Hash table. + def initialize_copy(orig) # :nodoc: super @table = @table.dup @table.each_key{|key| new_ostruct_member(key)} @@ -104,25 +106,27 @@ class OpenStruct # # Converts the OpenStruct to a hash with keys representing - # each attribute (as symbols) and their corresponding values - # Example: + # each attribute (as symbols) and their corresponding values. # - # require 'ostruct' - # data = OpenStruct.new("country" => "Australia", :population => 20_000_000) - # data.to_h # => {:country => "Australia", :population => 20000000 } + # require "ostruct" + # data = OpenStruct.new("country" => "Australia", :capital => "Canberra") + # data.to_h # => {:country => "Australia", :capital => "Canberra" } # def to_h @table.dup end # - # Yields all attributes (as a symbol) along with the corresponding values - # or returns an enumerator if not block is given. - # Example: + # :call-seq: + # ostruct.each_pair {|name, value| block } -> ostruct + # ostruct.each_pair -> Enumerator + # + # Yields all attributes (as symbols) along with the corresponding values + # or returns an enumerator if no block is given. # - # require 'ostruct' - # data = OpenStruct.new("country" => "Australia", :population => 20_000_000) - # data.each_pair.to_a # => [[:country, "Australia"], [:population, 20000000]] + # require "ostruct" + # data = OpenStruct.new("country" => "Australia", :capital => "Canberra") + # data.each_pair.to_a # => [[:country, "Australia"], [:capital, "Canberra"]] # def each_pair return to_enum(__method__) { @table.size } unless block_given? @@ -191,35 +195,50 @@ class OpenStruct end end - # Returns the value of a member. # - # person = OpenStruct.new('name' => 'John Smith', 'age' => 70) - # person[:age] # => 70, same as ostruct.age + # :call-seq: + # ostruct[name] -> object + # + # Returns the value of an attribute. + # + # require "ostruct" + # person = OpenStruct.new("name" => "John Smith", "age" => 70) + # person[:age] # => 70, same as person.age # def [](name) @table[name.to_sym] end # - # Sets the value of a member. + # :call-seq: + # ostruct[name] = obj -> obj + # + # Sets the value of an attribute. # - # person = OpenStruct.new('name' => 'John Smith', 'age' => 70) - # person[:age] = 42 # => equivalent to ostruct.age = 42 - # person.age # => 42 + # require "ostruct" + # person = OpenStruct.new("name" => "John Smith", "age" => 70) + # person[:age] = 42 # equivalent to person.age = 42 + # person.age # => 42 # def []=(name, value) modifiable[new_ostruct_member(name)] = value end # - # Remove the named field from the object. Returns the value that the field + # Removes the named field from the object. Returns the value that the field # contained if it was defined. # - # require 'ostruct' + # require "ostruct" # - # person = OpenStruct.new('name' => 'John Smith', 'age' => 70) + # person = OpenStruct.new(name: "John", age: 70, pension: 300) # - # person.delete_field('name') # => 'John Smith' + # person.delete_field("age") # => 70 + # person # => # + # + # Setting the value to +nil+ will not remove the attribute: + # + # person.pension = nil + # person # => # # def delete_field(name) sym = name.to_sym @@ -263,6 +282,14 @@ class OpenStruct # +other+ when +other+ is an OpenStruct and the two objects' Hash tables are # equal. # + # require "ostruct" + # first_pet = OpenStruct.new("name" => "Rowdy") + # second_pet = OpenStruct.new(:name => "Rowdy") + # third_pet = OpenStruct.new("name" => "Rowdy", :age => nil) + # + # first_pet == second_pet # => true + # first_pet == third_pet # => false + # def ==(other) return false unless other.kind_of?(OpenStruct) @table == other.table @@ -278,9 +305,11 @@ class OpenStruct @table.eql?(other.table) end - # Compute a hash-code for this OpenStruct. - # Two hashes with the same content will have the same hash code - # (and will be eql?). + # Computes a hash code for this OpenStruct. + # Two OpenStruct objects with the same content will have the same hash code + # (and will compare using #eql?). + # + # See also Object#hash. def hash @table.hash end -- cgit v1.2.3