Class: Throne::Tasks
- Inherits:
-
Object
- Object
- Throne::Tasks
- Defined in:
- lib/throne/tasks.rb,
lib/tasks.rb
Overview
Defines tasks for managing databases and views.
To reference a file in lib/ from your design doc, use a comment like this
// !code library.js
This will include the contents at this location.
These tasks require an environment variable of SERVER_URL to be set.
The documents should be stored using the following structure - all items in the root of base path will be included in all databases, items with a database will be included into that database only.
base_path/
|-- lib
| `-- library.js
|-- data
| `-- .json and .yml folders with seed data
|-- design
| `-- <design doc name>
| |-- lists
| | `-- listname.js
| |-- shows
| | `-- showname.js
| |-- validate_doc_update.js
| `-- views
| `-- statuses
| |-- map.js
| `-- reduce.js
|-- <db name>
|-- lib
| `-- library.js
|-- data
| `-- .json and .yml folders with seed data
`-- design
`-- <design doc name>
|-- lists
| `-- listname.js
|-- shows
| `-- showname.js
|-- validate_doc_update.js
`-- views
`-- statuses
|-- map.js
`-- reduce.js
Class Method Summary collapse
- .dump_docs_from_db(db, base_path, format) ⇒ Object
-
.inject_tasks(base_path) ⇒ Object
This will inject Rake tasks for managing the database data.
-
.load_data_for_database(db_url, base_path, database) ⇒ Object
Loads data into the database url from the source path.
-
.load_design_documents(db_url, base_path, database) ⇒ Object
Loads design documents into the database url, extracted from the source path The docs should be layed out in the following format: ‘– <design doc name> |– lists | `– statuses | `– list.js `– views `– statuses |– map.js `– reduce.js.
Class Method Details
.dump_docs_from_db(db, base_path, format) ⇒ Object
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/throne/tasks.rb', line 260 def self.dump_docs_from_db(db, base_path, format) raise "You must specify a DB name to dump task[dbname]" unless db outdir = File.join(base_path, db, "data") FileUtils.mkdir_p(outdir) unless File.exists?(outdir) @db = Throne::Database.new(url(db)) docs = [] @db.function('_all_docs') do |res| docs << @db.get(res['key']) unless res['key'].match(/^_/) end outfn = format == :json ? 'dump.json' : 'dump.yml' File.open(File.join(outdir, outfn), 'w') do |f| if format == :json f.puts JSON.pretty_generate(docs) elsif format == :yml f.puts docs.to_yaml else raise("Internal Error - invalid dump format specified") end end puts "Data dumped to #{base_path + '/' + db + '/' + outfn}" end |
.inject_tasks(base_path) ⇒ Object
This will inject Rake tasks for managing the database data. The base path should be where all the items are stored.
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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/throne/tasks.rb', line 55 def self.inject_tasks(base_path) namespace :throne do namespace :documents do namespace :load do databases_in_path(base_path).each do |dbname, fulldir| desc "Loads data for database #{dbname}, optionally into db" task dbname.to_sym, :db do |t, args| load_data_for_database(url(dbname, args), base_path, dbname) end end desc "load all dbs" task :all => databases_in_path(base_path) end namespace :dump do desc "Dump data for a database into a YAML file" task :yml, :db do |t, args| dump_docs_from_db(args.db, base_path, :yml) end desc "Dump data for a database into a JSON file" task :json, :db do |t, args| dump_docs_from_db(args.db, base_path, :json) end end end #design tasks namespace :design do namespace :push do databases_in_path(base_path).each do |dbname, fulldir| desc "pushes designs for database #{dbname}, optionally into db" task dbname.to_sym, :db do |t, args| load_design_documents(url(dbname, args), base_path, dbname) end end desc "push all designs" task :all => databases_in_path(base_path) end end # Db Tasks namespace :database do desc "Creates a database if it doesn't exist" task :createdb, :db do |t, args| get_db(args).create_database puts "Database at #{url(args.db)}" end desc "Deletes a database" task :deletedb, :db do |t, args| get_db(args).delete_database puts "Database at #{url(args.db)}" end desc "Deletes, creates and re-loads a database" task :rebuilddb, :db do |t, args| db = get_db(args) raise "you must specify the database name (task[db])" unless args.db db.delete_database # re-getting the object will create the DB db = get_db(args) # load design docs load_design_documents(db.url, base_path, args.db) # load data load_data_for_database(db.url, base_path, args.db) puts "Done." end end def self.get_db(args) args ? db = args.db : db = nil unless (ENV['SERVER_URL'] && args.db) || ENV['DB_URL'] raise "You must specify DB_URL or task[db_name] and SERVER_URL" end Throne::Database.new(url(db)) end end end |
.load_data_for_database(db_url, base_path, database) ⇒ Object
Loads data into the database url from the source path. Picks up .yml and .json
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/throne/tasks.rb', line 213 def self.load_data_for_database(db_url, base_path, database) @db = Throne::Database.new(db_url) items = [] doccount = 0 # grab and parse all YML files paths_for_item(base_path, database, 'data/**/*.yml').each do |yml| items << YAML::load(File.open(yml)) end # and json paths_for_item(base_path, database, 'data/**/*.json').each do |json| items << JSON.parse(File.open(json).read) end # load em up items.each do |item| if item.kind_of? Array item.each do |doc| begin @db.save(doc) rescue RestClient::RequestFailed => e if e. =~ /409$/ puts "Duplicate document - this data has probaby already been loaded" doccount -= 1 else raise e end end doccount += 1 end elsif item.kind_of? Hash begin @db.save(item) rescue RestClient::RequestFailed => e if e. =~ /409$/ puts "Duplicate document - this data has probaby already been loaded" doccount -= 1 else raise e end end doccount += 1 else puts "There is something funky with the data for #{source_path}" end end puts "#{doccount} document(s) loaded into database at #{@db.url}" end |
.load_design_documents(db_url, base_path, database) ⇒ Object
Loads design documents into the database url, extracted from the source path The docs should be layed out in the following format:
`-- <design doc name>
|-- lists
| `-- statuses
| `-- list.js
`-- views
`-- statuses
|-- map.js
`-- reduce.js
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/throne/tasks.rb', line 149 def self.load_design_documents(db_url, base_path, database) # for each folder in base path, create a new design doc key # create a lists key # for each path in lists, add a key with the folder name # inside this, there is a key called list, with the contents of the list function # views is the same, except with a map and reduce function paths_for_item(base_path, database, 'design/*').each do |doc_path| doc_name = File.basename(doc_path) doc = {'lists' => {}, 'views' => {}, 'shows' => {}} Dir.glob(File.join(doc_path, 'lists', '*.js')) do |list_path| list_name = File.basename(list_path).split('.').first doc['lists'][list_name] = {} doc['lists'][list_name] = inject_code_includes(base_path, database, list_path) end Dir.glob(File.join(doc_path, 'shows', '*.js')) do |show_path| show_name = File.basename(show_path).split('.').first doc['shows'][show_name] = {} doc['shows'][show_name] = inject_code_includes(base_path, database, show_path) end if File.exists?(vfn = File.join(doc_path, 'validate_doc_update.js')) doc['validate_doc_update'] = inject_code_includes(base_path, database, vfn) end Dir.glob(File.join(doc_path, 'views', '*')) do |view_path| view_name = File.basename(view_path) doc['views'][view_name] = {} mapfn = File.join(view_path, 'map.js') reducefn = File.join(view_path, 'reduce.js') doc['views'][view_name]['map'] = inject_code_includes(base_path, database, mapfn) if File.exists?(mapfn) doc['views'][view_name]['reduce'] = inject_code_includes(base_path, database, reducefn) if File.exists?(reducefn) end # try to get the existing doc doc_id = "_design/#{doc_name}" db = Throne::Database.new(db_url) if svr_doc = db.get(doc_id) # merge doc = svr_doc.merge(doc) else doc['_id'] = doc_id end doc['language'] = 'javascript' db.save(doc) puts "Design documents from #{doc_path} loaded" end # try and get a document with the design name # if it's there, replace the lists and views keys with above data # otherwise, create a new document, set language to javascript # put document. # WIN end |