summaryrefslogtreecommitdiff
path: root/vendor/gems/couchrest_session_store/lib/couchrest/session/document.rb
blob: b1e73cc4437c95b9d90b5476d3095a7a29d6960c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
require 'couchrest/session/utility'
require 'time'

class CouchRest::Session::Document < CouchRest::Document
  include CouchRest::Model::Configuration
  include CouchRest::Model::Connection
  include CouchRest::Session::Utility
  include CouchRest::Model::Rotation

  rotate_database 'sessions',
    :every => 1.month, :expiration_field => :expires

  def self.fetch(sid)
    self.allocate.tap do |session_doc|
      session_doc.fetch(sid)
    end
  end

  def self.build(sid, session, options = {})
    self.new(CouchRest::Document.new({"_id" => sid})).tap do |session_doc|
      session_doc.update session, options
    end
  end

  def self.build_or_update(sid, session, options = {})
    options[:marshal_data] = true if options[:marshal_data].nil?
    doc = self.fetch(sid)
    doc.update(session, options)
    return doc
  rescue CouchRest::NotFound
    self.build(sid, session, options)
  end

  def self.find_by_expires(options = {})
    options[:reduce] ||= false
    design = database.get '_design/Session'
    response = design.view :by_expires, options
    response['rows']
  end

  def self.create_database!(name=nil)
    db = super(name)
    begin
      db.get('_design/Session')
    rescue CouchRest::NotFound
      design = File.read(File.expand_path('../../../../design/Session.json', __FILE__))
      design = JSON.parse(design)
      db.save_doc(design.merge({"_id" => "_design/Session"}))
    end
    db
  end

  def initialize(doc)
    @doc = doc
  end

  def fetch(sid = nil)
    @doc = database.get(sid || doc['_id'])
  end

  def to_session
    if doc["marshalled"]
      session = unmarshal(doc["data"])
    else
      session = doc["data"]
    end
    return session
  end

  def delete
    database.delete_doc(doc)
  end

  def update(session, options)
    # clean up old data but leave id and revision intact
    doc.reject! do |k,v|
      k[0] != '_'
    end
    doc.merge! data_for_doc(session, options)
  end

  def save
    database.save_doc(doc)
  rescue CouchRest::Conflict
    fetch
    retry
  rescue CouchRest::NotFound => exc
    if exc.http_body =~ /no_db_file/
      exc = CouchRest::StorageMissing.new(exc.response, database)
    end
    raise exc
  end

  def expired?
    expires && expires < Time.now
  end

  protected

  def data_for_doc(session, options)
    { "data" => options[:marshal_data] ? marshal(session) : session,
      "marshalled" => options[:marshal_data],
      "expires" => expiry_from_options(options) }
  end

  def expiry_from_options(options)
    expire_after = options[:expire_after]
    expire_after && (Time.now + expire_after).utc
  end

  def expires
    doc["expires"] && Time.iso8601(doc["expires"])
  end

  def doc
    @doc
  end

end