论坛首页 编程语言技术论坛

rails2.3的cookies

浏览 4225 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-10-24   最后修改:2009-10-25
2.1.2下

  • cookies每次随着用户访问都会发送的服务器
  • cookies只能存储字符串
  • cookie是一种类似于Hash的结构,但它的类型是ActionController#cookies


它和普通的hash类似,在操作上有些不同
# example 1
def index
	cookies[:name] = "kitty"
	p cookies[:name]
end

# 第一次访问
# => nil

# 第二次访问
# => kitty


引用一段对此说明
引用

cookies in rails is of type CookieJar. CookieJar manages incoming and outgoing cookie information and works as follows.


到这,这一切都没什么问题。但疑惑的地方从2.3.4出现了

# example 1
def index
	cookies[:name] = "kitty"
	cookies[:age] = 20
	p cookies[:age].class
	p cookies[:name]
end

# 第一次访问
# => Fixnum
# => Kitty

# 第二次访问
# => Fixnum
# => kitty

cookies在存储值后立马可以访问了,而且也能存储除字符串以外的类型(貌似很奇怪)
这个版本的cookies和session从用法上来讲,好像就没有区别了

找了些相关的资料,也没有找出个所以然来,貌似对rails cookies的讨论不是很多,望指教
   发表时间:2009-10-25   最后修改:2009-10-25
这个cookies在写入客户端的时候仍然只能是字符串..

还有你第一次已经在客户机上设置name => kitty的cookie了
下次访问当然有了...

你可以清空cookie再试一次。。

这是actioncontroller的cookie.rb源码。写的很明白了。
module ActionController #:nodoc:
  # Cookies are read and written through ActionController#cookies.
  #
  # The cookies being read are the ones received along with the request, the cookies
  # being written will be sent out with the response. Reading a cookie does not get
  # the cookie object itself back, just the value it holds.
  #
  # Examples for writing:
  #
  #   # Sets a simple session cookie.
  #   cookies[:user_name] = "david"
  #
  #   # Sets a cookie that expires in 1 hour.
  #   cookies[:login] = { :value => "XJ-122", :expires => 1.hour.from_now }
  #
  # Examples for reading:
  #
  #   cookies[:user_name] # => "david"
  #   cookies.size        # => 2
  #
  # Example for deleting:
  #
  #   cookies.delete :user_name
  #
  # Please note that if you specify a :domain when setting a cookie, you must also specify the domain when deleting the cookie:
  #
  #  cookies[:key] = {
  #    :value => 'a yummy cookie',
  #    :expires => 1.year.from_now,
  #    :domain => 'domain.com'
  #  }
  #
  #  cookies.delete(:key, :domain => 'domain.com')
  #
  # The option symbols for setting cookies are:
  #
  # * <tt>:value</tt> - The cookie's value or list of values (as an array).
  # * <tt>:path</tt> - The path for which this cookie applies.  Defaults to the root
  #   of the application.
  # * <tt>:domain</tt> - The domain for which this cookie applies.
  # * <tt>:expires</tt> - The time at which this cookie expires, as a Time object.
  # * <tt>:secure</tt> - Whether this cookie is a only transmitted to HTTPS servers.
  #   Default is +false+.
  # * <tt>:httponly</tt> - Whether this cookie is accessible via scripting or
  #   only HTTP. Defaults to +false+.
  module Cookies
    def self.included(base)
      base.helper_method :cookies
    end

    protected
      # Returns the cookie container, which operates as described above.
      def cookies
        @cookies ||= CookieJar.new(self)
      end
  end

  class CookieJar < Hash #:nodoc:
    def initialize(controller)
      @controller, @cookies = controller, controller.request.cookies
      super()
      update(@cookies)
    end

    # Returns the value of the cookie by +name+, or +nil+ if no such cookie exists.
    def [](name)
      super(name.to_s)
    end

    # Sets the cookie named +name+. The second argument may be the very cookie
    # value, or a hash of options as documented above.
    def []=(key, options)
      if options.is_a?(Hash)
        options.symbolize_keys!
      else
        options = { :value => options }
      end

      options[:path] = "/" unless options.has_key?(:path)
      super(key.to_s, options[:value])
      @controller.response.set_cookie(key, options)
    end

    # Removes the cookie on the client machine by setting the value to an empty string
    # and setting its expiration date into the past. Like <tt>[]=</tt>, you can pass in
    # an options hash to delete cookies with extra data such as a <tt>:path</tt>.
    def delete(key, options = {})
      options.symbolize_keys!
      options[:path] = "/" unless options.has_key?(:path)
      super(key.to_s)
      @controller.response.delete_cookie(key, options)
    end
  end
end


0 请登录后投票
   发表时间:2009-10-25   最后修改:2009-10-25
Hooopo 写道

还有你第一次已经在客户机上设置name => kitty的cookie了
下次访问当然有了...

你可以清空cookie再试一次。。


这个在我进行测试的时候已经清空了,不知道你有没有对比两个版本测试过

对于2.3中cookies可以在设置值后不用response到客户端就可以访问的现象是否和这句话有关
    # Sets the cookie named +name+. The second argument may be the very cookie
    # value, or a hash of options as documented above.
    def []=(key, options)
      if options.is_a?(Hash)
        options.symbolize_keys!
      else
        options = { :value => options }
      end

      options[:path] = "/" unless options.has_key?(:path)
      super(key.to_s, options[:value]) #=> 我指的是这一句,但是编辑器没有能给变色显示
      @controller.response.set_cookie(key, options)
    end

这是我对比2.1的源代码得到的结论。

至于2.3中cooikes的value可以是对象类型(不仅仅是我上面说过的数值类型,Time也是可以往里存的),在我顺着源代码往上找,一直找到request,而request里面是没有cookies方法的,我猜想可能是它的父类里了吧,但是
class Request < Rack::Request

到这,我就跟丢了
0 请登录后投票
   发表时间:2009-10-29  


是的,这句就是关键
  super(key.to_s, options[:value]) #=> 我指的是这一句,但是编辑器没有能给变色显示  


因为:
controller 中的cookies方法,就是CookieJar实例:
# Cookies are read and written through ActionController#cookies.
  module Cookies
      ...
      def cookies
        CookieJar.new(self)
      end
  end


而CookieJar是扩展了一个Hash类:
  class CookieJar < Hash #:nodoc:
  ...
  end


并覆盖了HASH的元素读、写方法:
    def [](name)
      super(name.to_s)
    end

    def []=(key, options)
      ...
      super(key.to_s, options[:value])
      @controller.response.set_cookie(key, options)
    end


可以想象普通的HASH对象读写,什么都能存放:
@cookies = Hash.new
@cookies['mykey'] = AnyThing
puts @cookies['mykey'] #=> AnyThing


只是CookieJar在保存值时,通过@controller.response.set_cookie把值序列化(一般是调用to_s),如果值无法序列化存储的,下次读取出来的肯定会变成空值,因此你要正确测试COOKIE的读写的话,应该分两次request,如:
  def write_cookies
    cookies['mykey'] = 'some text'
    cookies['wrong_value'] = self
    redirect_to :action => 'read_cookies'
  end

  def read_cookies
    render :inline => %{
      <xmp>
        mykey = #{cookies['mykey']}
        wrong_value = #{cookies['wrong_value']}
      </xmp>
    }
  end

否则在同一个action里,读来写去只不过是对同一个HASH对象操作,自然会Rails cookies有“万能”存储的错觉。
3 请登录后投票
   发表时间:2009-10-30  
刚才又试了一次,确实疏忽了,无论存储什么内容,在服务器response之前是可以原样访问的,但response之后再request,就都是字符串了

谢谢你
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics