Rails源码 attr_internal

Posted by wxianfeng Thu, 05 Jan 2012 18:34:00 GMT

环境:ruby 1.9.2 + rails 3.0.3 + ubuntu 10.10

params在rails中很常用,特别在表单提交的时候,params 产生的是一个Hash ,里面构造通过 form域的name构造 ,产生不同的 params 内容,今天 在看rails params 实现的时候 发现通过 attr_internal 的方法实现,params方法 的源码:

    def params
      @_params ||= request.parameters
    end

发现其实是从 request 这个方法得到的,那么request方法又是怎么定义的:

attr_internal :headers, :response, :request

就是 用了 attr_internal 方法

看下 整个 metal.rb文件: here

发现了 response,headers,session(借助delegate委派) ,status,params == 都是通过 attr_internal 实现的,来看看 attr_internal 到底是何须人也 :

源码: here

class Module
  # Declares an attribute reader backed by an internally-named instance variable.
  def attr_internal_reader(*attrs)
    attrs.each do |attr|
      module_eval "def #{attr}() #{attr_internal_ivar_name(attr)} end", __FILE__, __LINE__
    end
  end

  # Declares an attribute writer backed by an internally-named instance variable.
  def attr_internal_writer(*attrs)
    attrs.each do |attr|
      module_eval "def #{attr}=(v) #{attr_internal_ivar_name(attr)} = v end", __FILE__, __LINE__
    end
  end

  # Declares an attribute reader and writer backed by an internally-named instance
  # variable.
  def attr_internal_accessor(*attrs)
    attr_internal_reader(*attrs)
    attr_internal_writer(*attrs)
  end

  alias_method :attr_internal, :attr_internal_accessor

  class << self; attr_accessor :attr_internal_naming_format end
  self.attr_internal_naming_format = '@_%s'

  private
    def attr_internal_ivar_name(attr)
      Module.attr_internal_naming_format % attr
    end
end

发现其实就是通过 module_eval 给 对象 添加了 settet , getter 方法而已,但是命名格式是这样的:

  self.attr_internal_naming_format = '@_%s' 

DEMO:

require "active_support/core_ext/module/attr_internal"

class Foo
  
  attr_accessor :sex,:birthday # attr_accessor ruby里封装的method
  attr_internal :name,:city # attr_internal rails 封装的

  def bar
    name # call getter method # => @_name
  end

end

f = Foo.new
f.name = 'wxianfeng'
p f.instance_variables # => [:@_name]
p f.name # => "wxianfeng"
p f # => #<Foo:0x8630e18 @_name="wxianfeng">
p f.bar # => "wxianfeng"

所以 attr_internal 和 attr_accessor 其实是 等价的,只不过 从字面意思上看是内部变量(闭包变量的写法) ,attr_internal 希望你 通过方法名来调用,不用 @_%s 这个写法 来调用


所以 其实 一般我们在 controller 用的 request 方法 其实 可以直接这样写 @_request ,

request #=> @_request
params # => @_request.parameters
params # => @_params
headers #=> @_headers
status #=> @_status
.
.
.

但是一般 不建议这样写

还发现 这些和 http相关的东西都定义在 metal 模块, metal 是 rails 链接 rack 的中间件,源码中的解释:

ActionController::Metal provides a way to get a valid Rack application from a controller.

Rack 是一个 ruby实现的web server,封装了 http的请求和响应等,例如 rails,sinatra == 都是在 rack 基础上实现的……

有机会很有必要 深入学习下…

SEE:

http://rubyonrailswin.wordpress.com/2007/03/07/actioncontroller-and-what-the-heck-is-attr_internal/
http://www.oschina.net/p/rack

This entry was posted on Thu, 05 Jan 2012 18:34:00 GMT and Posted in . You can follow any any response to this entry through the Atom feed. You can leave a comment or a trackback from your own site.

Tags , ,


Trackbacks

Use the following link to trackback from your own site:
http://wxianfeng.com/trackbacks?article_id=162

Comments

  1. Avatar
    Joey {{count}} months ago:

    Rack要好好看阿 2.3开始就是rails on rack了
    toto sinatra还有好些都是基于rack的
    这玩意儿强大的 绝对值得一看

  2. Avatar
    Joey {{count}} months ago:

    还有你的博文越来越有深度了
    加油
    : )

  3. Avatar
    wxianfeng {{count}} months ago:

    @Joey
    多谢,最近 在狠看 rails 源码,发现 元编程 用的 太多了,难怪rails 跑起来慢的!

  4. Avatar
    rothbuildersverobeach.net over {{count}} years ago:

    I know this web site ofers quality based comtent
    andd other data, is there any other web page which provides these things in quality?

  5. Avatar
    rothbuildersverobeach.net over {{count}} years ago:

    I know this web site offers quality based content and otfher data, is theee any other web
    page which provides these things in quality?

Leave a comment