Class: CouchResource::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/couch_resource/base.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes = nil) ⇒ Base

Returns a new instance of Base.



547
548
549
550
551
552
553
554
555
556
557
# File 'lib/couch_resource/base.rb', line 547

def initialize(attributes = nil)
  if attributes
    (self.class.read_inheritable_attribute(:attribute_members) || {}).each do |name, option|
      self.set_attribute(name, attributes[name.to_sym])
    end
    @id  = attributes[:_id] ? attributes[:_id] : nil
    @rev = attributes[:_rev] ? attributes[:_rev] : nil
  end
  # invoke explicit callback
  self.after_initialize rescue NoMethodError
end

Class Method Details

.all_docs_path(query_options = nil) ⇒ Object

Returns the path of _all_docs API



102
103
104
# File 'lib/couch_resource/base.rb', line 102

def all_docs_path(query_options=nil)
  document_path("_all_docs", query_options)
end

.bulk_docs(array = []) ⇒ Object

Execute bulk_docs transaction. Each element in the array is passed to the “docs” member in the request body.

This method returns the raw hash of JSON from CouchDB.

Examples)

bulk_docs([1,2,3]) --->
   POST /{db}/_bulk_docs

   { "docs" : [1,2,3] }

bulk_docs([{ :_id => "1", :_rev => "1234", :foo      => "bar" },
           { :_id => "1", :_rev => "5678", :_deleted => true }]) --->
   POST /{db}/_bulk_docs

   { "docs" : [
         { "_id" : "1" , "_rev" : "1234", "foo"      : "bar" },
         { "_id" : "2" , "_rev" : "5678", "_deleted" : true },
      ] }


225
226
227
228
229
230
231
232
# File 'lib/couch_resource/base.rb', line 225

def bulk_docs(array = [])
  document = { :docs => array }
  logger.debug "CouchResource::Connection#post #{bulk_docs_path}"
  logger.debug document.to_json
  result = connection.post(bulk_docs_path, document.to_json)
  logger.debug result.inspect
  result
end

.bulk_docs_pathObject

Returns the path of _bulk_docs



107
108
109
# File 'lib/couch_resource/base.rb', line 107

def bulk_docs_path
  document_path("_bulk_docs")
end

.connection(reflesh = false) ⇒ Object

An instance of CouchResource::Connection that is the base connection to the remote service. The refresh parameter toggles whether or not the connection is refreshed at every request or not (defaults to false).



84
85
86
87
88
89
90
91
92
93
94
# File 'lib/couch_resource/base.rb', line 84

def connection(reflesh = false)
  if defined?(@connection) || superclass == Object
    @connection = Connection.new(database) if reflesh || @connection.nil?
    @connection.user = user if user
    @connection.password = password if password
    @connection.timeout = timeout if timeout
    @connection
  else
    superclass.connection
  end
end

.databaseObject

Get the URI of the CouchDB database to map for this class



13
14
15
16
17
18
19
# File 'lib/couch_resource/base.rb', line 13

def database
  if defined?(@database)
    @database
  elsif superclass != Object && superclass.database
    superclass.database.dup.freeze
  end
end

.database=(uri) ⇒ Object Also known as: set_database

Set the URI of the CouchDB database to map for this class



22
23
24
25
26
27
28
29
30
31
# File 'lib/couch_resource/base.rb', line 22

def database=(uri)
  @connection = nil
  if uri.nil?
    @database = nil
  else
    @database = uri.is_a?(URI) ? uri.dup : URI.parse(uri)
    @user     = URI.decode(@database.user) if @database.user
    @password = URI.decode(@database.password) if @database.password
  end
end

.defaultObject



234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/couch_resource/base.rb', line 234

def default
  obj = self.new
  (self.read_inheritable_attribute(:attribute_members) || {}).each do |name, option|
    if option.has_key?(:default)
      default = option[:default]
      if default.is_a?(Proc)
        obj.set_attribute(name, default.call())
      else
        obj.set_attribute(name, default)
      end
    end
  end
  obj
end

.document_path(id, query_options = nil) ⇒ Object

Get the document path specified by the document id



97
98
99
# File 'lib/couch_resource/base.rb', line 97

def document_path(id, query_options=nil)
  "#{File.join(database.path, id)}#{query_string(query_options)}"
end

.exists?(id, options = nil) ⇒ Boolean

Get whether the document specified by id exists or not options are

  • :rev - An string value determining the revision of the document.

Returns:

  • (Boolean)


126
127
128
129
130
131
132
133
# File 'lib/couch_resource/base.rb', line 126

def exists?(id, options=nil)
  if id
    headers = {}
    headers["If-Match"] = options[:rev].to_json if options[:rev]
    path = document_path(id, options)
    result = connection.head(path, headers)
  end
end

.find(*args) ⇒ Object

Find the existant document and returns the document object mapped to this class.

Examples

Document.find(1)
Document.find("abceef")
Document.find(1, 2, 3)
Document.find([1,2,3])
Document.find(1,:rev => 123456)

Note that when the first argument is one of :first, :last or :all, this finder method requests a view name to retrieve documents. In this case options can be the same as CouchDB’s querying options (wiki.apache.org/couchdb/HttpViewApi).

* <tt>key</tt>            - an object value determining key parameter.
* <tt>startkey</tt>       - an object value determining startkey parameter.
* <tt>startkey_docid</tt> - a string value determiming startkey_docid parameter.
* <tt>endkey</tt>         - an object value determining endkey parameter.
* <tt>endkey_docid</tt>   - a string value determiming startkey_docid parameter.
* <tt>count</tt>          - an integer value determining count parameter.
* <tt>descending</tt>     - a boolean value determining descending parameter.
* <tt>skip</tt>           - an integer value determining skip parameter.
* <tt>group</tt>          - an boolean value determining group parameter.
* <tt>group_level</tt>    - an integer value determining gropu_level parameter.

Common Options

* return_raw_hash       - if set true, finder method returns row hash of the response

Examples

Document.find(:first, "design_name", "view_name")
Document.find(:first, "design_name", "view_name", :key => "abcd")
Document.find(:first, "design_name", "view_name",
              :startkey => ["abcd"], :endkey => ["abcd", "ZZZZ"],
              :descending => true)
Document.find(:last,  "design_name", "view_name")
Document.find(:all,   "design_name", "view_name")


188
189
190
191
192
193
194
195
196
197
198
# File 'lib/couch_resource/base.rb', line 188

def find(*args)
  options = args.extract_options!
  case args.first
  when :first, :last, :all
    raise ArgumentError.new("Design name must be specified. ") unless args[1]
    raise ArgumentError.new("View name must be specified. ") unless args[2]
    send("find_#{args.first}",  args[1], args[2], options)
  else
    find_from_ids(*(args << options))
  end
end

.get_revs(id, detailed = false) ⇒ Object

Get the document revisions specified by id</ttd> This method returns an array including revision numbers. If the second argument, <tt>detailed, is true, each element in the result array is a Hash which contains 2 key, “status” and “revision”. If false, each element is a string which represents revision number.



140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/couch_resource/base.rb', line 140

def get_revs(id, detailed = false)
  if id
    if detailed
      path = document_path(id, { :revs_info => true })
      result = connection.get(path)
      result[:_revs_info].map { |r| r.symbolize_keys! }
    else
      path = document_path(id, { :revs => true })
      result = connection.get(path)
      result[:_revs]
    end
  end
end

.human_attribute_name(attribute_key_name) ⇒ Object

Returns human readable attribute name



201
202
203
# File 'lib/couch_resource/base.rb', line 201

def human_attribute_name(attribute_key_name) #:nodoc:
  attribute_key_name.humanize
end

.passwordObject

Gets the password for REST HTTP authentication.



51
52
53
54
55
56
57
58
# File 'lib/couch_resource/base.rb', line 51

def password
  # Not using superclass_delegating_reader. See +site+ for explanation
  if defined?(@password)
    @password
  elsif superclass != Object && superclass.password
    superclass.password.dup.freeze
  end
end

.password=(password) ⇒ Object

Sets the password for REST HTTP authentication.



61
62
63
64
# File 'lib/couch_resource/base.rb', line 61

def password=(password)
  @connection = nil
  @password = password
end

.query_string(query_options = nil) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
# File 'lib/couch_resource/base.rb', line 111

def query_string(query_options=nil)
  # compatibility :count and :limit
  if query_options.nil? || query_options.empty?
    nil
  else
    q = query_options.dup
    q[:limit] = q.delete(:count) if q.has_key?(:count)
    "?#{q.to_query}"
  end

end

.timeoutObject

Gets tthe number of seconds after which requests to the REST API should time out.



73
74
75
76
77
78
79
# File 'lib/couch_resource/base.rb', line 73

def timeout
  if defined?(@timeout)
    @timeout
  elsif superclass != Object && superclass.timeout
    superclass.timeout
  end
end

.timeout=(timeout) ⇒ Object

Sets the number of seconds after which requests to the REST API should time out.



67
68
69
70
# File 'lib/couch_resource/base.rb', line 67

def timeout=(timeout)
  @connection = nil
  @timeout = timeout
end

.userObject

Gets the user for REST HTTP authentication.



35
36
37
38
39
40
41
42
# File 'lib/couch_resource/base.rb', line 35

def user
  # Not using superclass_delegating_reader. See +site+ for explanation
  if defined?(@user)
    @user
  elsif superclass != Object && superclass.user
    superclass.user.dup.freeze
  end
end

.user=(user) ⇒ Object

Sets the user for REST HTTP authentication.



45
46
47
48
# File 'lib/couch_resource/base.rb', line 45

def user=(user)
  @connection = nil
  @user = user
end

Instance Method Details

#destroyObject



596
597
598
599
600
601
602
603
604
605
606
# File 'lib/couch_resource/base.rb', line 596

def destroy
  if self.new_record?
    false
  else
    # [TODO] This does not work on couchdb 0.9.0 (returns 400 'Document rev and etag have different values.')
    # connection.delete(document_path, {"If-Match" => rev })
    connection.delete(document_path)
    @rev = nil
    true
  end
end

#document_pathObject

Get the path of the object.



617
618
619
620
621
622
623
# File 'lib/couch_resource/base.rb', line 617

def document_path
  if rev
    self.class.document_path(id, { :rev => rev })
  else
    self.class.document_path(id)
  end
end

#exists?Boolean

Returns:

  • (Boolean)


608
609
610
611
612
613
614
# File 'lib/couch_resource/base.rb', line 608

def exists?
  if rev
    !new? && self.class.exists?(id, { :rev => rev })
  else
    !new? && self.class.exists?(id)
  end
end

#idObject Also known as: _id



564
565
566
# File 'lib/couch_resource/base.rb', line 564

def id
  @id
end

#id=(id) ⇒ Object Also known as: _id=



569
570
571
# File 'lib/couch_resource/base.rb', line 569

def id=(id)
  @id=id
end

#new?Boolean Also known as: new_record?

Returns:

  • (Boolean)


559
560
561
# File 'lib/couch_resource/base.rb', line 559

def new?
  rev.nil?
end

#revObject Also known as: _rev



574
575
576
# File 'lib/couch_resource/base.rb', line 574

def rev
  @rev
end

#revs(detailed = false) ⇒ Object



579
580
581
# File 'lib/couch_resource/base.rb', line 579

def revs(detailed = false)
  new? ? [] : self.class.get_revs(self.id, detailed)
end

#saveObject



583
584
585
# File 'lib/couch_resource/base.rb', line 583

def save
  result = create_or_update
end

#save!Object



587
588
589
# File 'lib/couch_resource/base.rb', line 587

def save!
  save || raise(RecordNotSaved)
end

#to_jsonObject

Get the json representation of the object.



626
627
628
629
630
631
# File 'lib/couch_resource/base.rb', line 626

def to_json
  h = self.to_hash
  h[:id]  = self.id  if self.id
  h[:rev] = self.rev if self.rev
  h.to_json
end

#to_xmlObject

Get the xml representation of the object, whose root is the class name.



634
635
636
637
638
639
# File 'lib/couch_resource/base.rb', line 634

def to_xml
  h = self.to_hash
  h[:id]  = self.id  if self.id
  h[:rev] = self.rev if self.rev
  h.to_xml(:root => self.class.to_s)
end

#update_attribute(name, value) ⇒ Object



591
592
593
594
# File 'lib/couch_resource/base.rb', line 591

def update_attribute(name, value)
  send("#{name.to_s}=", value)
  save
end