`
Hooopo
  • 浏览: 335157 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

OpenStruct

    博客分类:
  • Ruby
阅读更多
#
# = ostruct.rb: OpenStruct implementation
#
# Author:: Yukihiro Matsumoto
# Documentation:: Gavin Sinclair
#
# OpenStruct allows the creation of data objects with arbitrary attributes.
# See OpenStruct for an example.
#

#
# OpenStruct allows you to create data objects and set arbitrary attributes.
# For example:
#
#   require 'ostruct' 
#
#   record = OpenStruct.new
#   record.name    = "John Smith"
#   record.age     = 70
#   record.pension = 300
#   
#   puts record.name     # -> "John Smith"
#   puts record.address  # -> nil
#
# It is like a hash with a different way to access the data.  In fact, it is
# implemented with a hash, and you can initialize it with one.
#
#   hash = { "country" => "Australia", :population => 20_000_000 }
#   data = OpenStruct.new(hash)
#
#   p data        # -> <OpenStruct country="Australia" population=20000000>
#
class OpenStruct
  #
  # Create a new OpenStruct object.  The optional +hash+, if given, will
  # generate attributes and values.  For example.
  #
  #   require 'ostruct'
  #   hash = { "country" => "Australia", :population => 20_000_000 }
  #   data = OpenStruct.new(hash)
  #
  #   p data        # -> <OpenStruct country="Australia" population=20000000>
  #
  # By default, the resulting OpenStruct object will have no attributes. 
  #
  def initialize(hash=nil)
    @table = {}
    if hash
      for k,v in hash
        @table[k.to_sym] = v
        new_ostruct_member(k)
      end
    end
  end

  # Duplicate an OpenStruct object members. 
  def initialize_copy(orig)
    super
    @table = @table.dup
  end

  def marshal_dump
    @table
  end
  def marshal_load(x)
    @table = x
    @table.each_key{|key| new_ostruct_member(key)}
  end

  def new_ostruct_member(name)
    name = name.to_sym
    unless self.respond_to?(name)
      meta = class << self; self; end
      meta.send(:define_method, name) { @table[name] }
      meta.send(:define_method, :"#{name}=") { |x| @table[name] = x }
    end
  end

  def method_missing(mid, *args) # :nodoc:
    mname = mid.id2name
    len = args.length
    if mname =~ /=$/
      if len != 1
        raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller(1)
      end
      if self.frozen?
        raise TypeError, "can't modify frozen #{self.class}", caller(1)
      end
      mname.chop!
      self.new_ostruct_member(mname)
      @table[mname.intern] = args[0]
    elsif len == 0
      @table[mid]
    else
      raise NoMethodError, "undefined method `#{mname}' for #{self}", caller(1)
    end
  end

  #
  # Remove the named field from the object.
  #
  def delete_field(name)
    @table.delete name.to_sym
  end

  InspectKey = :__inspect_key__ # :nodoc:

  #
  # Returns a string containing a detailed summary of the keys and values.
  #
  def inspect
    str = "#<#{self.class}"

    Thread.current[InspectKey] ||= []
    if Thread.current[InspectKey].include?(self) then
      str << " ..."
    else
      first = true
      for k,v in @table
        str << "," unless first
        first = false

        Thread.current[InspectKey] << v
        begin
          str << " #{k}=#{v.inspect}"
        ensure
          Thread.current[InspectKey].pop
        end
      end
    end

    str << ">"
  end
  alias :to_s :inspect

  attr_reader :table # :nodoc:
  protected :table

  #
  # Compare this object and +other+ for equality.
  #
  def ==(other)
    return false unless(other.kind_of?(OpenStruct))
    return @table == other.table
  end
end



断网了闲着无聊看代码...
几点疑问:
1.这个initialize_copy怎么就成了私有方法了?
def initialize_copy(orig)
    super
    @table = @table.dup
  end


2.貌似在不用send的情况下,即使传入多个参数(多个参数被转换成array了)args.length也是1

len = args.length
    if mname =~ /=$/
      if len != 1
        #......



分享到:
评论

相关推荐

    recursive-open-struct:OpenStruct子类,将嵌套的哈希属性作为RecursiveOpenStructs返回

    OpenStruct子类,该子类将嵌套的哈希属性作为RecursiveOpenStructs返回。 用法 它允许在一系列方法中调用哈希中的哈希: ros = RecursiveOpenStruct . new ( { wha : { tagoo : 'siam' } } ) ros . wha . tagoo # =...

    themoviedb-api:使用OpenStruct为电影数据库API提供简单直观的界面

    使用OpenStruct为电影数据库API提供简单直观的界面。 获取您的API密钥。 入门 在Rails应用内安装 将此行添加到您的应用程序的Gemfile中: gem 'themoviedb-api' 安装外部Rails应用 gem install themoviedb - ...

    Ruby的25个编程细节(技巧、实用代码段)

    **Struct** 和 **OpenStruct** 都是用来创建简单的数据容器的类,但它们之间存在一些显著的区别: - **Struct** 在定义时需要明确声明所有字段,而 **OpenStruct** 可以动态添加属性。 - 性能方面,**Struct** 优于...

    fast_open_struct:打开结构,不会在每次实例化时都使ruby的方法缓存无效

    FastOpenStruct是Ruby OpenStruct的重新实现,可以避免在每次实例化时使MRI的方法缓存无效。 应该可以替代OpenStruct。 表现 当您的OpenStructs倾向于具有静态属性集时,FastOpenStruct会非常快: λ ruby -I./...

    blockhead:用于封送对象的简单 DSL

    安装将此行添加到应用程序的 Gemfile 中: gem 'blockhead'然后执行: $ bundle或者自己安装: $ gem install blockhead用法假设您有以下对象,其中包含一些 1:1 和 1:M 的关系属性集: object = OpenStruct ....

    rottentomatoes:RottenTomatoes.com 的 ActiveRecord 风格的 API 包装器

    烂番茄 烂番茄是一个ActiveRecord风格的API包装 。 rottentomatoes 旨在使常见任务比直接处理基于 URL 的 API 更容易。...# =&gt; &lt;OpenStruct&gt; @movie = RottenMovie . find ( :imdb =&gt; 137523 ) # =&gt; &lt;OpenStruct&gt; @m

    ruby-tmdb:[已弃用] TheMovieDB.org 的 ActiveRecord 样式 API 包装器

    请注意,这回购已被弃用 RubyTMDB ruby-tmdb 是的 ActiveRecord 风格的 API 包装器。... find ( :title =&gt; "Iron Man" , :limit =&gt; 1 )# =&gt; &lt;OpenStruct&gt;@movie . name# =&gt; "Iron Man"@movie . posters . length

    immutable-struct:创建没有 setter 但有一个很棒的构造函数的类结构类

    除了使用Hash或OpenStruct ,您还可以使用ImmutableStruct使您的类型更加清晰,这几乎同样方便。 安装 添加到您的Gemfile : gem 'immutable-struct' 然后安装: bundle install 如果不使用 bundler,只需使用 ...

    super_serial:Rails的序列化,关于类固醇

    超级串行 安装 将此行添加到您的应用程序的Gemfile中: gem 'super_serial' ... 在后台,它在SuperHero的功能列中序列化了一个OpenStruct。 然后,它为每个键值对或“输入”定义访问器方法。 superman = Supe

    performant_ruby

    - OpenFastStruct 是一种数据结构,类似于 OpenStruct 但速度快 网络框架 - 罗达 http://lotusrb.org/ - 莲花 哈希构建器/序列化器 https://github.com/mindreframer/api_view - 该死的快速序列化器 gem 简单的...

    limdesk_api:Limdesk.com API 包装器 Ruby Gem

    这个 gem 将 Limdesk API 包装到 OpenStruct (RecursiveOpenStruct) 对象中。 有关 API 的更多信息,请查看。 当前 API 涵盖了基本的、最常见的操作。 更高级的版本目前正在开发中。 连接到 API LimdeskApi . ...

    log-parser:解析给定日志文件的日志

    日志解析器 解析给定日志文件的日志并返回页面浏览量。 如何使用。 运行Ruby脚本 ... 最初的实现是将每个IP地址和页面存储在OpenStruct中。 但随后将重复IP地址和页面。 这对于测试以及内存都不理想。 因

    设计模式

    在Ruby中,可以使用OpenStruct或Delegator实现: ```ruby require 'forwardable' class RealObject def some_method "Real object's method" end end class Proxy extend Forwardable def_delegators :@real...

    parsers:用于Web解析的简单线程库

    Based: Capybara; Nokogiri; RSpec; Selenium; Mechanize;Written on pure Ruby, using: Threads/Queue/Mutex/OpenStruct/StoreCheck: bin/start Test bundle exec rspec

    super_struct:扩展结构构造函数

    对Struct简单扩展,使其与Hash更兼容,而没有OpenStruct的性能损失 安装 将此行添加到应用程序的 Gemfile 中: gem 'super_struct' 然后执行: $ bundle 或者自己安装: $ gem install super_struct 用法 ...

Global site tag (gtag.js) - Google Analytics