Merge branch 'master' of git://github.com/jchris/couchrest

* 'master' of git://github.com/jchris/couchrest: (21 commits)
  require before include
  require system
  deep include
  change it to !include
  use the lib dir
  lib not library
  more reorg for couchapp
  remove couchview
  modernizing couchapp
  simpler mappings
  simplyfy couchapp push
  extract method
  removed doc.json special case
  hand merge mattly time patch
  removed the suffix and duplication when importing views
  added possibility to cast any key to any type using any method
  push forms/ into _design/$this/forms
  push forms/ into _design/$this/forms
  Fixed the "save bug should fix" spec
  add txt mimetype
  ...
This commit is contained in:
Matt Lyon 2009-01-03 18:06:23 -08:00
commit 189cd910a3
28 changed files with 329 additions and 334 deletions

View file

@ -31,7 +31,7 @@ CouchRest install, from the project root directory run `rake`, or `autotest`
Quick Start:
# with !, it creates the database if it doesn't already exist
@db = CouchRest.database!("http://localhost:5984/couchrest-test")
@db = CouchRest.database!("http://127.0.0.1:5984/couchrest-test")
response = @db.save({:key => 'value', 'another key' => 'another value'})
doc = @db.get(response['id'])
puts doc.inspect

View file

@ -5,7 +5,7 @@ require 'rake/gempackagetask'
spec = Gem::Specification.new do |s|
s.name = "couchrest"
s.version = "0.10.1"
s.version = "0.11.1"
s.date = "2008-11-22"
s.summary = "Lean and RESTful interface to CouchDB."
s.email = "jchris@grabb.it"
@ -19,7 +19,6 @@ spec = Gem::Specification.new do |s|
s.extra_rdoc_files = %w( README.rdoc LICENSE THANKS )
s.require_path = "lib"
s.bindir = 'bin'
s.executables << 'couchview'
s.executables << 'couchdir'
s.executables << 'couchapp'
s.add_dependency("json", ">= 1.1.2")

View file

@ -1,48 +0,0 @@
#!/usr/bin/env ruby
require 'optparse'
require 'couchrest'
%w(generate push).each do |file|
require File.dirname(__FILE__) + "/../lib/couchrest/commands/#{file}"
end
# Set defaults
options = {
:loud => true,
}
opts = OptionParser.new do |opts|
opts.banner = "Usage: #$0 [options] (push|generate) directory database"
opts.on('-q', '--quiet', "Omit extra debug info") do
options[:loud] = false
end
opts.on_tail('-h', '--help [push|generate]', "Display detailed help and exit") do |help_command|
puts opts
case help_command
when "push"
puts CouchRest::Commands::Push.help
when "generate"
puts CouchRest::Commands::Generate.help
end
exit
end
end
opts.parse!(ARGV)
options[:command] = ARGV.shift
options[:directory] = ARGV.shift
options[:trailing_args] = ARGV
# There must be a better way to check for extra required args
unless (["push", "generate"].include?(options[:command]) && options[:directory] && options[:trailing_args])
puts(opts)
exit
end
case options[:command]
when "push"
CouchRest::Commands::Push.run(options)
when "generate"
CouchRest::Commands::Generate.run(options)
end

View file

@ -1,17 +1,16 @@
Gem::Specification.new do |s|
s.extra_rdoc_files = ["README.rdoc", "LICENSE", "THANKS"]
s.date = "Sat Nov 22 00:00:00 -0800 2008"
s.executables = ["couchview", "couchdir", "couchapp"]
s.executables = ["couchdir", "couchapp"]
s.authors = ["J. Chris Anderson"]
s.required_rubygems_version = ">= 0"
s.version = "0.10.1"
s.version = "0.11.1"
s.files = ["LICENSE",
"README.rdoc",
"Rakefile",
"THANKS",
"bin/couchapp",
"bin/couchdir",
"bin/couchview",
"examples/model",
"examples/model/example.rb",
"examples/word_count",
@ -43,11 +42,21 @@ Gem::Specification.new do |s|
"lib/couchrest/helper/file_manager.rb",
"lib/couchrest/helper/pager.rb",
"lib/couchrest/helper/streamer.rb",
"lib/couchrest/helper/templates",
"lib/couchrest/helper/templates/bar.txt",
"lib/couchrest/helper/templates/example-map.js",
"lib/couchrest/helper/templates/example-reduce.js",
"lib/couchrest/helper/templates/index.html",
"lib/couchrest/helper/template-app",
"lib/couchrest/helper/template-app/_attachments",
"lib/couchrest/helper/template-app/_attachments/index.html",
"lib/couchrest/helper/template-app/foo",
"lib/couchrest/helper/template-app/foo/bar.txt",
"lib/couchrest/helper/template-app/forms",
"lib/couchrest/helper/template-app/forms/example-form.js",
"lib/couchrest/helper/template-app/forms/lib",
"lib/couchrest/helper/template-app/forms/lib/example-template.html",
"lib/couchrest/helper/template-app/views",
"lib/couchrest/helper/template-app/views/_lib",
"lib/couchrest/helper/template-app/views/_lib/helper.js",
"lib/couchrest/helper/template-app/views/example",
"lib/couchrest/helper/template-app/views/example/map.js",
"lib/couchrest/helper/template-app/views/example/reduce.js",
"lib/couchrest/monkeypatches.rb",
"lib/couchrest.rb",
"spec/couchapp_spec.rb",

View file

@ -2,7 +2,7 @@
require File.expand_path(File.dirname(__FILE__)) + '/../../couchrest'
cr = CouchRest.new("http://localhost:5984")
cr = CouchRest.new("http://127.0.0.1:5984")
@db = cr.database('word-count-example')
@word_memoizer = {}

View file

@ -1,6 +1,6 @@
require File.dirname(__FILE__) + '/../../couchrest'
couch = CouchRest.new("http://localhost:5984")
couch = CouchRest.new("http://127.0.0.1:5984")
db = couch.database('word-count-example')
db.delete! rescue nil
db = couch.create_db('word-count-example')
@ -62,6 +62,6 @@ end
# }
# })
# puts "The books have been stored in your CouchDB. To initiate the MapReduce process, visit http://localhost:5984/_utils/ in your browser and click 'word-count-example', then select view 'words' or 'count'. The process could take about 15 minutes on an average MacBook."
# puts "The books have been stored in your CouchDB. To initiate the MapReduce process, visit http://127.0.0.1:5984/_utils/ in your browser and click 'word-count-example', then select view 'words' or 'count'. The process could take about 15 minutes on an average MacBook."
#

View file

@ -1,6 +1,6 @@
require File.dirname(__FILE__) + '/../../couchrest'
couch = CouchRest.new("http://localhost:5984")
couch = CouchRest.new("http://127.0.0.1:5984")
db = couch.database('word-count-example')
puts "Now that we've parsed all those books into CouchDB, the queries we can run are incredibly flexible."
@ -35,5 +35,5 @@ puts "\nHere are the params for 'flight' in the da-vinci book:"
puts params.inspect
puts
puts 'The url looks like this:'
puts 'http://localhost:5984/word-count-example/_view/word_count/count?key=["flight","da-vinci"]'
puts 'http://127.0.0.1:5984/word-count-example/_view/word_count/count?key=["flight","da-vinci"]'
puts "\nTry dropping that in your browser..."

View file

@ -72,7 +72,7 @@ module CouchRest
db = nil if db && db.empty?
{
:host => host || "localhost:5984",
:host => host || "127.0.0.1:5984",
:database => db,
:doc => docid
}

View file

@ -52,7 +52,7 @@ module CouchRest
foo-project/bar-views/my-design/viewname-reduce.js
foo-project/bar-views/my-design/noreduce-map.js
Pushed to => http://localhost:5984/baz-database/_design/my-design
Pushed to => http://127.0.0.1:5984/baz-database/_design/my-design
And the design document:
{
@ -81,11 +81,11 @@ module CouchRest
(for project global libs). These libraries are only inserted into views which
include the text
//include-lib
// !include lib
or
#include-lib
# !include lib
Couchview is a result of scratching my own itch. I'd be happy to make it more
general, so please contact me at jchris@grabb.it if you'd like to see anything

View file

@ -18,7 +18,7 @@ module CouchRest
# than this example.
#
# class Article < CouchRest::Model
# use_database CouchRest.database!('http://localhost:5984/couchrest-model-test')
# use_database CouchRest.database!('http://127.0.0.1:5984/couchrest-model-test')
# unique_id :slug
#
# view_by :date, :descending => true
@ -519,16 +519,17 @@ module CouchRest
self.class.casts.each do |k,v|
next unless self[k]
target = v[:as]
v[:send] || 'new'
if target.is_a?(Array)
klass = ::Extlib::Inflection.constantize(target[0])
self[k] = self[k].collect do |value|
klass == Time ? Time.parse(value) : klass.new(value)
(!v[:send] && klass == Time) ? Time.parse(value) : klass.send((v[:send] || 'new'), value)
end
else
self[k] = if target == 'Time'
self[k] = if (!v[:send] && target == 'Time')
Time.parse(self[k])
else
::Extlib::Inflection.constantize(target).new(self[k])
::Extlib::Inflection.constantize(target).send((v[:send] || 'new'), self[k])
end
end
end

View file

@ -1,7 +1,7 @@
module CouchRest
class Server
attr_accessor :uri, :uuid_batch_count
def initialize server = 'http://localhost:5984', uuid_batch_count = 1000
def initialize server = 'http://127.0.0.1:5984', uuid_batch_count = 1000
@uri = server
@uuid_batch_count = uuid_batch_count
end

View file

@ -12,12 +12,63 @@ module CouchRest
"png" => "image/png",
"gif" => "image/gif",
"css" => "text/css",
"js" => "test/javascript"
}
def initialize(dbname, host="http://localhost:5984")
"js" => "test/javascript",
"txt" => "text/plain"
}
def initialize(dbname, host="http://127.0.0.1:5984")
@db = CouchRest.new(host).database(dbname)
end
def push_app(appdir, appname)
libs = []
viewdir = File.join(appdir,"views")
attachdir = File.join(appdir,"_attachments")
@doc = dir_to_fields(appdir)
package_forms(@doc["forms"])
package_views(@doc["views"])
docid = "_design/#{appname}"
design = @db.get(docid) rescue {}
design.merge!(@doc)
design['_id'] = docid
# design['language'] = lang if lang
@db.save(design)
push_directory(attachdir, docid)
end
def dir_to_fields(dir)
fields = {}
(Dir["#{dir}/**/*.*"] -
Dir["#{dir}/_attachments/**/*.*"]).each do |file|
farray = file.sub(dir, '').sub(/^\//,'').split('/')
myfield = fields
while farray.length > 1
front = farray.shift
myfield[front] ||= {}
myfield = myfield[front]
end
fname, fext = farray.shift.split('.')
fguts = File.open(file).read
if fext == 'json'
myfield[fname] = JSON.parse(fguts)
else
myfield[fname] = fguts
end
end
return fields
end
# Generate an application in the given directory.
# This is a class method because it doesn't depend on
# specifying a database.
def self.generate_app(app_dir)
templatedir = File.join(File.expand_path(File.dirname(__FILE__)), 'template-app')
FileUtils.cp_r(templatedir, app_dir)
end
def push_directory(push_dir, docid=nil)
docid ||= push_dir.split('/').reverse.find{|part|!part.empty?}
@ -37,7 +88,7 @@ module CouchRest
@attachments[name] = {
"data" => value,
"content_type" => MIMES[name.split('.').last]
}
}
end
doc = @db.get(docid) rescue nil
@ -97,191 +148,76 @@ module CouchRest
end
end
def push_views(view_dir)
designs = {}
Dir["#{view_dir}/**/*.*"].each do |design_doc|
design_doc_parts = design_doc.split('/')
next if /^lib\..*$/.match design_doc_parts.last
pre_normalized_view_name = design_doc_parts.last.split("-")
view_name = pre_normalized_view_name[0..pre_normalized_view_name.length-2].join("-")
folder = design_doc_parts[-2]
designs[folder] ||= {}
designs[folder]["views"] ||= {}
design_lang = design_doc_parts.last.split(".").last
designs[folder]["language"] ||= LANGS[design_lang]
libs = ""
Dir["#{view_dir}/lib.#{design_lang}"].collect do |global_lib|
libs << open(global_lib).read
libs << "\n"
end
Dir["#{view_dir}/#{folder}/lib.#{design_lang}"].collect do |global_lib|
libs << open(global_lib).read
libs << "\n"
end
if design_doc_parts.last =~ /-map/
designs[folder]["views"]["#{view_name}-map"] ||= {}
designs[folder]["views"]["#{view_name}-map"]["map"] = read(design_doc, libs)
designs[folder]["views"]["#{view_name}-reduce"] ||= {}
designs[folder]["views"]["#{view_name}-reduce"]["map"] = read(design_doc, libs)
end
if design_doc_parts.last =~ /-reduce/
designs[folder]["views"]["#{view_name}-reduce"] ||= {}
designs[folder]["views"]["#{view_name}-reduce"]["reduce"] = read(design_doc, libs)
end
end
# cleanup empty maps and reduces
designs.each do |name, props|
props["views"].each do |view, funcs|
next unless view.include?("reduce")
props["views"].delete(view) unless funcs.keys.include?("reduce")
end
end
designs.each do |k,v|
create_or_update("_design/#{k}", v)
end
designs
end
def pull_views(view_dir)
prefix = "_design"
ds = db.documents(:startkey => '#{prefix}/', :endkey => '#{prefix}/ZZZZZZZZZ')
ds['rows'].collect{|r|r['id']}.each do |id|
puts directory = id.split('/').last
FileUtils.mkdir_p(File.join(view_dir,directory))
views = db.get(id)['views']
vgroups = views.keys.group_by{|k|k.sub(/\-(map|reduce)$/,'')}
vgroups.each do|g,vs|
mapname = vs.find {|v|views[v]["map"]}
if mapname
# save map
mapfunc = views[mapname]["map"]
mapfile = File.join(view_dir, directory, "#{g}-map.js") # todo support non-js views
File.open(mapfile,'w') do |f|
f.write mapfunc
end
end
reducename = vs.find {|v|views[v]["reduce"]}
if reducename
# save reduce
reducefunc = views[reducename]["reduce"]
reducefile = File.join(view_dir, directory, "#{g}-reduce.js") # todo support non-js views
File.open(reducefile,'w') do |f|
f.write reducefunc
end
end
end
end
end
def push_app(appdir, appname)
libs = []
viewdir = File.join(appdir,"views")
attachdir = File.join(appdir,"_attachments")
views, lang = read_design_views(viewdir)
docid = "_design/#{appname}"
design = @db.get(docid) rescue {}
design['_id'] = docid
design['views'] = views
design['language'] = lang if lang
@db.save(design)
push_directory(attachdir, docid)
push_fields(appdir, docid)
end
def push_fields(appdir, docid)
fields = {}
(Dir["#{appdir}/**/*.*"] -
Dir["#{appdir}/views/**/*.*"] -
Dir["#{appdir}/doc.json"] -
Dir["#{appdir}/_attachments/**/*.*"]).each do |file|
farray = file.sub(appdir, '').sub(/^\//,'').split('/')
myfield = fields
while farray.length > 1
front = farray.shift
myfield[front] ||= {}
myfield = myfield[front]
end
fname, fext = farray.shift.split('.')
fguts = File.open(file).read
if fext == 'json'
myfield[fname] = JSON.parse(fguts)
else
myfield[fname] = fguts
end
end
if File.exists?("#{appdir}/doc.json")
default_json = JSON.parse(File.open("#{appdir}/doc.json").read)
end
design = @db.get(docid) rescue {}
design.merge!(fields)
design.merge!(default_json) if default_json
@db.save(design)
end
# Generate an application in the given directory.
# This is a class method because it doesn't depend on
# specifying a database.
def self.generate_app(app_dir)
FileUtils.mkdir_p(app_dir)
FileUtils.mkdir_p(File.join(app_dir,"_attachments"))
FileUtils.mkdir_p(File.join(app_dir,"views"))
FileUtils.mkdir_p(File.join(app_dir,"foo"))
{
"index.html" => "_attachments",
'example-map.js' => "views",
'example-reduce.js' => "views",
'bar.txt' => "foo",
}.each do |filename, targetdir|
template = File.join(File.expand_path(File.dirname(__FILE__)), 'templates',filename)
dest = File.join(app_dir,targetdir,filename)
FileUtils.cp(template, dest)
end
end
private
def read_design_views(viewdir)
libs = []
language = nil
views = {}
Dir["#{viewdir}/*.*"].each do |viewfile|
view_parts = viewfile.split('/')
viewfile_name = view_parts.last
# example-map.js
viewfile_name_parts = viewfile_name.split('.')
viewfile_ext = viewfile_name_parts.last
view_name_parts = viewfile_name_parts.first.split('-')
func_type = view_name_parts.pop
view_name = view_name_parts.join('-')
contents = File.open(viewfile).read
if /^lib\..*$/.match viewfile_name
libs.push(contents)
else
views[view_name] ||= {}
language = LANGS[viewfile_ext]
views[view_name][func_type] = contents.sub(/(\/\/|#)include-lib/,libs.join("\n"))
end
end
[views, language]
def package_forms(funcs)
apply_lib(funcs)
end
def package_views(views)
views.each do |view, funcs|
apply_lib(funcs)
end
end
def apply_lib(funcs)
funcs.each do |k,v|
next unless v.is_a?(String)
funcs[k] = process_include(process_require(v))
end
end
# process requires
def process_require(f_string)
f_string.gsub /(\/\/|#)\ ?!require (.*)/ do
fields = $2.split('.')
library = @doc
fields.each do |field|
library = library[field]
break unless library
end
library
end
end
def process_include(f_string)
# process includes
included = {}
f_string.gsub /(\/\/|#)\ ?!include (.*)/ do
fields = $2.split('.')
library = @doc
include_to = included
count = fields.length
fields.each_with_index do |field, i|
break unless library[field]
library = library[field]
# normal case
if i+1 < count
include_to[field] = include_to[field] || {}
include_to = include_to[field]
else
# last one
include_to[field] = library
end
end
end
# puts included.inspect
rval = if included == {}
f_string
else
varstrings = included.collect do |k, v|
"var #{k} = #{v.to_json};"
end
f_string.sub /(\/\/|#)\ ?!include (.*)/, varstrings.join("\n")
end
rval
end
def say words
puts words if @loud
end
@ -289,29 +225,5 @@ module CouchRest
def md5 string
Digest::MD5.hexdigest(string)
end
def read(file, libs=nil)
st = open(file).read
st.sub!(/(\/\/|#)include-lib/,libs) if libs
st
end
def create_or_update(id, fields)
existing = @db.get(id) rescue nil
if existing
updated = existing.merge(fields)
if existing != updated
say "replacing #{id}"
db.save(updated)
else
say "skipping #{id}"
end
else
say "creating #{id}"
db.save(fields.merge({"_id" => id}))
end
end
end
end

View file

@ -0,0 +1,17 @@
function(doc, req) {
// !include lib.templates
// !require lib.helpers.template
respondWith(req, {
html : function() {
var html = template(lib.templates.example, doc);
return {body:html}
},
xml : function() {
return {
body : <xml><node value={doc.title}/></xml>
}
}
})
};

View file

@ -0,0 +1 @@
function stddev() {};

View file

@ -0,0 +1,32 @@
// Simple JavaScript Templating
// John Resig - http://ejohn.org/ - MIT Licensed
var cache = {};
function template(str, data){
// Figure out if we're getting a template, or if we need to
// load the template - and be sure to cache the result.
var fn = cache[str] ||
// Generate a reusable function that will serve as a template
// generator (and which will be cached).
new Function("obj",
"var p=[],print=function(){p.push.apply(p,arguments);};" +
// Introduce the data as local variables using with(){}
"with(obj){p.push('" +
// Convert the template into pure JavaScript
str
.replace(/[\r\t\n]/g, " ")
.replace(/'(?=[^%]*%>)/g,"\t")
.split("'").join("\\'")
.split("\t").join("'")
.replace(/<%=(.+?)%>/g, "',$1,'")
.split("<%").join("');")
.split("%>").join("p.push('")
+ "');}return p.join('');");
cache[str] = fn;
// Provide some basic currying to the user
return data ? fn( data ) : fn;
};

View file

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>Generated CouchApp Form Template</title>
</head>
<body>
<div id="header">
<h2><a href="index.html">Back to index</a></h2>
</div>
<div id="content">
<h1><% doc.title %></h1>
</div>
</body>
<script src="/_utils/script/json2.js"></script>
<script src="/_utils/script/jquery.js?1.2.6"></script>
<script src="/_utils/script/jquery.couch.js?0.8.0"></script>
<script src="jquery.couchapp.js"></script>
<script src="blog.js"></script>
<script type="text/javascript" charset="utf-8">
$.CouchApp(function(app) {
var docid = document.location.pathname.split('/').pop();
// hey you could run a query to load more information from views
});
</script>
<script src="showdown.js"></script>
</html>

View file

@ -1,5 +1,6 @@
// an example map function, emits the doc id
// and the list of keys it contains
// !require lib.helpers.math
function(doc) {
var k, keys = []

View file

@ -16,14 +16,26 @@ describe "couchapp" do
end
describe "generate my-app" do
before(:all) do
`#{@run} generate my-app`.should match(/generating/i)
end
it "should create an app directory" do
`#{@run} generate my-app`.should match(/generating/i)
Dir["#{@fixdir}/*"].select{|x|x =~ /my-app/}.length.should == 1
end
it "should create a views directory" do
`#{@run} generate my-app`.should match(/generating/i)
Dir["#{@fixdir}/my-app/*"].select{|x|x =~ /views/}.length.should == 1
end
it "should create an _attachments directory" do
Dir["#{@fixdir}/my-app/*"].select{|x|x =~ /_attachments/}.length.should == 1
Dir["#{@fixdir}/my-app/_attachments/*"].select{|x|x =~ /index.html/}.length.should == 1
end
it "should create a forms directory" do
Dir["#{@fixdir}/my-app/*"].select{|x|x =~ /forms/}.length.should == 1
end
it "should create a forms and libs" do
Dir["#{@fixdir}/my-app/forms/*"].select{|x|x =~ /example-form.js/}.length.should == 1
Dir["#{@fixdir}/my-app/lib/templates/*"].select{|x|x =~ /example.html/}.length.should == 1
end
end
describe "push my-app #{TESTDB}" do
@ -33,26 +45,38 @@ describe "couchapp" do
@db.delete! rescue nil
@db = @cr.create_db(TESTDB) rescue nil
`#{@run} generate my-app`
`#{@run} push my-app #{TESTDB}`
@doc = @db.get("_design/my-app")
end
it "should create the design document with the app name" do
`#{@run} push my-app #{TESTDB}`
lambda{@db.get("_design/my-app")}.should_not raise_error
end
it "should create the views" do
`#{@run} push my-app #{TESTDB}`
doc = @db.get("_design/my-app")
doc['views']['example']['map'].should match(/function/)
@doc['views']['example']['map'].should match(/function/)
end
it "should create the view libs" do
@doc['views']['example']['map'].should match(/stddev/)
@doc['forms']['example-form'].should_not match(/\"helpers\"/)
end
it "should create view for all the views" do
`echo 'moremap' > #{@fixdir}/my-app/views/more-map.js`
`mkdir -p #{@fixdir}/my-app/views/more`
`echo 'moremap' > #{@fixdir}/my-app/views/more/map.js`
`#{@run} push my-app #{TESTDB}`
doc = @db.get("_design/my-app")
doc['views']['more']['map'].should match(/moremap/)
end
it "should create the index" do
`#{@run} push my-app #{TESTDB}`
doc = @db.get("_design/my-app")
doc['_attachments']['index.html']["content_type"].should == 'text/html'
@doc['_attachments']['index.html']["content_type"].should == 'text/html'
end
it "should push the forms" do
@doc['forms']['example-form'].should match(/Generated CouchApp Form Template/)
end
it "should allow deeper includes" do
@doc['forms']['example-form'].should_not match(/\"helpers\"/)
end
it "deep requires" do
@doc['forms']['example-form'].should_not match(/\"template\"/)
@doc['forms']['example-form'].should match(/Resig/)
end
end

View file

@ -46,48 +46,48 @@ describe CouchRest do
it "should parse just a dbname" do
db = CouchRest.parse "my-db"
db[:database].should == "my-db"
db[:host].should == "localhost:5984"
db[:host].should == "127.0.0.1:5984"
end
it "should parse a host and db" do
db = CouchRest.parse "localhost/my-db"
db = CouchRest.parse "127.0.0.1/my-db"
db[:database].should == "my-db"
db[:host].should == "localhost"
db[:host].should == "127.0.0.1"
end
it "should parse a host and db with http" do
db = CouchRest.parse "http://localhost/my-db"
db = CouchRest.parse "http://127.0.0.1/my-db"
db[:database].should == "my-db"
db[:host].should == "localhost"
db[:host].should == "127.0.0.1"
end
it "should parse a host with a port and db" do
db = CouchRest.parse "localhost:5555/my-db"
db = CouchRest.parse "127.0.0.1:5555/my-db"
db[:database].should == "my-db"
db[:host].should == "localhost:5555"
db[:host].should == "127.0.0.1:5555"
end
it "should parse a host with a port and db with http" do
db = CouchRest.parse "http://localhost:5555/my-db"
db = CouchRest.parse "http://127.0.0.1:5555/my-db"
db[:database].should == "my-db"
db[:host].should == "localhost:5555"
db[:host].should == "127.0.0.1:5555"
end
it "should parse just a host" do
db = CouchRest.parse "http://localhost:5555/"
db = CouchRest.parse "http://127.0.0.1:5555/"
db[:database].should be_nil
db[:host].should == "localhost:5555"
db[:host].should == "127.0.0.1:5555"
end
it "should parse just a host no slash" do
db = CouchRest.parse "http://localhost:5555"
db[:host].should == "localhost:5555"
db = CouchRest.parse "http://127.0.0.1:5555"
db[:host].should == "127.0.0.1:5555"
db[:database].should be_nil
end
it "should get docid" do
db = CouchRest.parse "localhost:5555/my-db/my-doc"
db = CouchRest.parse "127.0.0.1:5555/my-db/my-doc"
db[:database].should == "my-db"
db[:host].should == "localhost:5555"
db[:host].should == "127.0.0.1:5555"
db[:doc].should == "my-doc"
end
it "should get docid with http" do
db = CouchRest.parse "http://localhost:5555/my-db/my-doc"
db = CouchRest.parse "http://127.0.0.1:5555/my-db/my-doc"
db[:database].should == "my-db"
db[:host].should == "localhost:5555"
db[:host].should == "127.0.0.1:5555"
db[:doc].should == "my-doc"
end
@ -137,24 +137,24 @@ describe CouchRest do
describe "easy initializing a database adapter" do
it "should be possible without an explicit CouchRest instantiation" do
db = CouchRest.database "http://localhost:5984/couchrest-test"
db = CouchRest.database "http://127.0.0.1:5984/couchrest-test"
db.should be_an_instance_of(CouchRest::Database)
db.host.should == "localhost:5984"
db.host.should == "127.0.0.1:5984"
end
# TODO add https support (need test environment...)
# it "should work with https" # do
# db = CouchRest.database "https://localhost:5984/couchrest-test"
# db.host.should == "https://localhost:5984"
# db = CouchRest.database "https://127.0.0.1:5984/couchrest-test"
# db.host.should == "https://127.0.0.1:5984"
# end
it "should not create the database automatically" do
db = CouchRest.database "http://localhost:5984/couchrest-test"
db = CouchRest.database "http://127.0.0.1:5984/couchrest-test"
lambda{db.info}.should raise_error(RestClient::ResourceNotFound)
end
end
describe "ensuring the db exists" do
it "should be super easy" do
db = CouchRest.database! "http://localhost:5984/couchrest-test-2"
db = CouchRest.database! "http://127.0.0.1:5984/couchrest-test-2"
db.name.should == 'couchrest-test-2'
db.info["db_name"].should == 'couchrest-test-2'
end

View file

@ -159,7 +159,7 @@ describe CouchRest::Database do
docs = [{'key' => 'value'}, {'_id' => 'totally-uniq'}]
id_docs = [{'key' => 'value', '_id' => 'asdf6sgadkfhgsdfusdf'}, {'_id' => 'totally-uniq'}]
CouchRest.should_receive(:post).with("http://localhost:5984/couchrest-test/_bulk_docs", {:docs => id_docs})
CouchRest.should_receive(:post).with("http://127.0.0.1:5984/couchrest-test/_bulk_docs", {:docs => id_docs})
@db.bulk_save(docs)
end

View file

@ -46,7 +46,7 @@ class Course < CouchRest::Model
end
class Article < CouchRest::Model
use_database CouchRest.database!('http://localhost:5984/couchrest-model-test')
use_database CouchRest.database!('http://127.0.0.1:5984/couchrest-model-test')
unique_id :slug
view_by :date, :descending => true
@ -89,9 +89,18 @@ class Player < CouchRest::Model
timestamps!
end
class Event < CouchRest::Model
key_accessor :subject, :occurs_at
cast :occurs_at, :as => 'Time', :send => 'parse'
end
describe "save bug" do
before(:each) do
CouchRest::Model.default_database = reset_test_db!
end
it "should fix" do
@db = reset_test_db!
@p = Player.new
@p.email = 'insane@fakestreet.com'
@p.save
@ -107,8 +116,8 @@ describe CouchRest::Model do
@db = @cr.create_db(TESTDB) rescue nil
@adb = @cr.database('couchrest-model-test')
@adb.delete! rescue nil
CouchRest.database!('http://localhost:5984/couchrest-model-test')
CouchRest::Model.default_database = CouchRest.database!('http://localhost:5984/couchrest-test')
CouchRest.database!('http://127.0.0.1:5984/couchrest-model-test')
CouchRest::Model.default_database = CouchRest.database!('http://127.0.0.1:5984/couchrest-test')
end
it "should use the default database" do
@ -319,6 +328,18 @@ describe CouchRest::Model do
end
end
describe "cast keys to any type" do
before(:all) do
event_doc = { :subject => "Some event", :occurs_at => Time.now }
e = Event.database.save event_doc
@event = Event.get e['id']
end
it "should cast created_at to Time" do
@event['occurs_at'].should be_an_instance_of(Time)
end
end
describe "saving a model" do
before(:all) do
@obj = Basic.new

View file

@ -15,12 +15,12 @@ describe CouchRest::FileManager do
lambda{CouchRest::FileManager.new}.should raise_error
end
it "should accept a db name" do
@fm = CouchRest::FileManager.new(TESTDB, 'http://localhost')
@fm = CouchRest::FileManager.new(TESTDB, 'http://127.0.0.1')
@fm.db.name.should == TESTDB
end
it "should default to localhost couchdb" do
it "should default to 127.0.0.1 couchdb" do
@fm = CouchRest::FileManager.new(TESTDB)
@fm.db.host.should == 'http://localhost:5984'
@fm.db.host.should == 'http://127.0.0.1:5984'
end
end
@ -127,16 +127,16 @@ describe CouchRest::FileManager, "pushing views" do
@design["views"].should_not be_nil
end
it "should push a map and reduce view" do
@design["views"]["test-map"].should_not be_nil
@design["views"]["test-reduce"].should_not be_nil
@design["views"]["test"]["map"].should_not be_nil
@design["views"]["test"]["reduce"].should_not be_nil
end
it "should push a map only view" do
@design["views"]["only-map"].should_not be_nil
@design["views"]["only-reduce"].should be_nil
@design["views"]["only"]["map"].should_not be_nil
@design["views"]["only"]["reduce"].should be_nil
end
it "should include library files" do
@design["views"]["only-map"]["map"].should include("globalLib")
@design["views"]["only-map"]["map"].should include("justThisView")
@design["views"]["only"]["map"].should include("globalLib")
@design["views"]["only"]["map"].should include("justThisView")
end
it "should not create extra design docs" do
docs = @db.documents(:startkey => '_design', :endkey => '_design/ZZZZZZ')

View file

@ -5,7 +5,7 @@ require File.dirname(__FILE__) + '/../lib/couchrest'
FIXTURE_PATH = File.dirname(__FILE__) + '/fixtures'
COUCHHOST = "http://localhost:5984"
COUCHHOST = "http://127.0.0.1:5984"
TESTDB = 'couchrest-test'
def reset_test_db!

View file

@ -2,11 +2,11 @@ require 'rubygems'
require 'couchrest'
# set the source db and map view
source = CouchRest.new("http://localhost:5984").database('source-db')
source = CouchRest.new("http://127.0.0.1:5984").database('source-db')
source_view = 'mydesign/view-map'
# set the target db
target = CouchRest.new("http://localhost:5984").database('target-db')
target = CouchRest.new("http://127.0.0.1:5984").database('target-db')
pager = CouchRest::Pager.new(source)

View file

@ -5,10 +5,10 @@ require 'couchrest'
# use it to create a smaller dataset on which to prototype views.
# specify the source database
source = CouchRest.new("http://localhost:5984").database('source-db')
source = CouchRest.new("http://127.0.0.1:5984").database('source-db')
# specify the target database
target = CouchRest.new("http://localhost:5984").database('target-db')
target = CouchRest.new("http://127.0.0.1:5984").database('target-db')
# pager efficiently yields all view rows
pager = CouchRest::Pager.new(source)