Class: CouchClient::RakeTask

Inherits:
Rake::TaskLib
  • Object
show all
Defined in:
lib/couch-client/rake_task.rb

Overview

RakeTask is a namespace for all Rake tasks that are bundled with CouchClient, such as database creation, sync, compaction and deletion.

Defined Under Namespace

Classes: MissingCouchClientConnection

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(&block) ⇒ RakeTask

Start using CouchClient::RakeTask by constructing a new instance with a block.

CouchClient::RakeTask.new do |c|
  c.connection = Couch
  c.design_path = "./app/designs"
end

CouchClient::RakeTask.new takes the following options.

connection: A CouchClient Connection, default being `Couch`.
design_path: The path where design documents are stored, default being "./designs".


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
# File 'lib/couch-client/rake_task.rb', line 25

def initialize(&block)
  instance_eval(&block) if block_given?
  
  begin
    @connection ||= Object.const_get("Couch")
  rescue NameError
    raise MissingCouchClientConnection.new("specify a CouchClient connection within your RakeTask setup.")
  end
  
  @design_path = Pathname.new(@design_path || './designs')
  
  # Create Rake tasks.
  namespace :couch do
    desc "Syncs design documents with the database."
    task :sync do
      sync
    end
    
    desc "Creates the database."
    task :create do
      create
    end
    
    desc "Deletes the database and all its data."
    task :delete do
      delete
    end
    
    desc "Compacts the database."
    task :compact do
      compact
    end
  end
end

Instance Attribute Details

#connectionObject

Returns the value of attribute connection.



12
13
14
# File 'lib/couch-client/rake_task.rb', line 12

def connection
  @connection
end

#design_pathObject

Returns the value of attribute design_path.



12
13
14
# File 'lib/couch-client/rake_task.rb', line 12

def design_path
  @design_path
end

Instance Method Details

#compactObject



166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/couch-client/rake_task.rb', line 166

def compact
  resp = @connection.database.compact!
  
  if resp["ok"]
    puts "Compaction Complete."
  else
    utils_uri = lambda{
      handler = handler = @connection.hookup.handler
      handler.uri.gsub(/#{handler.database}$/, "_utils")
    }.call
    
    puts "The database could not be compacted, see #{utils_uri} for more information."
  end
end

#createObject



147
148
149
150
151
152
153
154
# File 'lib/couch-client/rake_task.rb', line 147

def create
  resp = @connection.database.create
  if resp["ok"]
    puts "Created."
  else
    puts "The database could not be created, the file already exists."
  end
end

#deleteObject



156
157
158
159
160
161
162
163
164
# File 'lib/couch-client/rake_task.rb', line 156

def delete
  resp = @connection.database.delete!
  
  if resp["ok"]
    puts "Deleted."
  else
    puts "The database could not be deleted, the file does not exist."
  end
end

#syncObject



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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/couch-client/rake_task.rb', line 60

def sync
  # Fetch all design documents that are cuurently saved in the database.
  saved_design_docs = @connection.all_design_docs("include_docs" => true)
  local_design_docs = {}
  
  design_path_depth = design_path.to_s.count("/") + 1
  
  # Recurse though the design directory and construct a hash of design functions.
  recurser = lambda do |path|
    path_breadcrumbs = path.to_s.match("[^\.]+")[0].split("/")[design_path_depth..-1] # e.g. ["people", "views", "all", "map"]
    path_hash_follow = path_breadcrumbs.reduce(""){|memo, key| memo + "['#{key}']"}   # e.g. ['people']['views']['all']['map']
    
    if path.directory?
      # Set an empty hash for the directory.
      eval("local_design_docs#{path_hash_follow} = {}")
      
      # Reject hidden filenames (filesnames that begin with a ".").
      path.children.reject{|p| p.basename.to_s.match(/^\./)}.each do |child|
        # Continue recursion.
        recurser.call(child)
      end
    else
      # Set a field with design function data.
      eval("local_design_docs#{path_hash_follow} = #{path.read.inspect}")
    end
  end
  
  recurser.call(@design_path)
  
  # Get a set of id's that are currently saved and a set that are avaiable locally.
  saved_ids = saved_design_docs.map{|doc| doc["id"].gsub(/^_design\//, "")}.to_set
  local_ids = local_design_docs.keys.to_set
  
  doc_ids_to_create = local_ids.difference(saved_ids).to_a
  doc_ids_to_update = saved_ids.intersection(local_ids).to_a
  doc_ids_to_delete = saved_ids.difference(local_ids).to_a
  
  # Create any new design documents.
  doc_ids_to_create.each do |id|
    new_doc = @connection.build
    new_doc.id = "_design/#{id}"
    new_doc.merge!(local_design_docs[id])
    new_doc.merge!({"language" => "javascript"})
    
    if new_doc.save
      puts "Creating: #{new_doc.id} -- #{new_doc.rev}"
    else
      puts "Failure:  #{new_doc.id} -- #{new_doc.error.inspect}"
    end
  end
  
  # Construct design documents that already exist.
  doc_ids_to_update.each do |id|
    old_doc = saved_design_docs.detect{|d| d["id"] == "_design/#{id}"}["doc"]
    
    new_doc = @connection.build
    new_doc.id  = old_doc.id
    new_doc.rev = old_doc.rev
    new_doc.merge!(local_design_docs[id])
    new_doc.merge!({"language" => "javascript"})
    
    # If the new document is the same as what is on the server
    if old_doc == new_doc
      # Keep the old design document.
      puts "Keeping:  #{new_doc.id} -- #{new_doc.rev}"
    else
      # Else save the new design docuemnt.
      if new_doc.save
        puts "Updating: #{new_doc.id} -- #{new_doc.rev}"
      else
        puts "Failure:  #{new_doc.id} -- #{new_doc.error.inspect}"
      end
    end
  end
  
  # Delete any documents that are not available locally.
  doc_ids_to_delete.each do |id|
    old_doc = saved_design_docs.detect{|d| d["id"] == "_design/#{id}"}["doc"]
    
    if old_doc.delete!
      puts "Deleting: #{old_doc.id} -- #{old_doc.rev}"
    else
      puts "Failure:  #{old_doc.id} -- #{new_doc.error.inspect}"
    end
  end
end