Skip to content

Commit

Permalink
Added commonJS support
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric committed Jun 19, 2013
1 parent 84d617a commit b464dd5
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 29 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,10 +293,10 @@ If you want Rails to automatically show a 404 page when `CouchPotato::NotFound`
render(:file => 'public/404.html', :status => :not_found, :layout => false)
end

You can also pass in custom map/reduce functions with the custom view spec:
You can also pass in custom map/reduce functions and CommonJS modules with the custom view spec:

class User
view :all, :map => "function(doc) { emit(doc.created_at, null)}", :include_docs => true, :type => :custom
view :all, :map => "function(doc) { emit(doc.created_at, null)}", :lib => {:test => "exports.test = 'test';"}, :include_docs => true, :type => :custom
end

If you don't want the results to be converted into models the raw view is your friend:
Expand Down
4 changes: 3 additions & 1 deletion lib/couch_potato/database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ def view(spec)
spec.design_document,
{spec.view_name => {
:map => spec.map_function,
:reduce => spec.reduce_function}
:reduce => spec.reduce_function,
:lib => spec.lib_function
}
},
({spec.list_name => spec.list_function} unless spec.list_name.nil?),
spec.language
Expand Down
2 changes: 1 addition & 1 deletion lib/couch_potato/view/base_view_spec.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module CouchPotato
module View
class BaseViewSpec
attr_reader :reduce_function, :list_name, :list_function, :design_document, :view_name, :klass, :options, :language
attr_reader :reduce_function, :lib_function, :list_name, :list_function, :design_document, :view_name, :klass, :options, :language
attr_accessor :view_parameters

private :klass, :options
Expand Down
4 changes: 4 additions & 0 deletions lib/couch_potato/view/custom_view_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ def reduce_function
options[:reduce]
end

def lib_function
options[:lib]
end

def view_parameters
{:include_docs => options[:include_docs] || false}.merge(super)
end
Expand Down
7 changes: 7 additions & 0 deletions lib/couch_potato/view/raw_view_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ module View
#
# example:
# view :my_custom_view, :map => "function(doc) { emit(doc._id, null); }", :type => :raw, :results_filter => lambda{|results| results['rows].map{|row| row['value']}}
#
# example:
# view :my_custom_view, :map => "function(doc) { emit(doc._id, null); }", :type => :raw, :lib => {:module => "exports.name = 'module';"
class RawViewSpec < BaseViewSpec
def map_function
options[:map]
Expand All @@ -16,6 +19,10 @@ def map_function
def reduce_function
options[:reduce]
end

def lib_function
options[:lib]
end
end
end
end
10 changes: 5 additions & 5 deletions lib/couch_potato/view/view_query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ def initialize(couchrest_database, design_document_name, view, list = nil, langu
@view_name = view.keys[0]
@map_function = view.values[0][:map]
@reduce_function = view.values[0][:reduce]
@lib_function = view.values[0][:lib]
@language = language
if list
@list_function = list.values[0]
Expand Down Expand Up @@ -42,11 +43,10 @@ def update_view
end

def view_functions
if @reduce_function
{'map' => @map_function, 'reduce' => @reduce_function}
else
{'map' => @map_function}
end
view = {'map' => @map_function}
view['reduce'] = @reduce_function if @reduce_function
view['lib'] = @lib_function if @lib_function
view
end

def empty_design_document
Expand Down
45 changes: 41 additions & 4 deletions spec/unit/database_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -342,32 +342,69 @@ def set_errors
CouchPotato::View::ViewQuery.stub(:new => stub('view query', :query_view! => {'rows' => [@result]}))
end

it "initialzes a view query with map/reduce/list funtions" do
it "initialzes a view query with map/reduce/list/lib funtions" do
@spec.stub(:design_document => 'design_doc', :view_name => 'my_view',
:map_function => '<map_code>', :reduce_function => '<reduce_code>',
:lib_function => {:test => '<test_code>'},
:list_name => 'my_list', :list_function => '<list_code>', :language => 'javascript')
CouchPotato::View::ViewQuery.should_receive(:new).with(
@couchrest_db,
'design_doc',
{'my_view' => {
:map => '<map_code>',
:reduce => '<reduce_code>'
:reduce => '<reduce_code>',
:lib => {:test => '<test_code>'}
}},
{'my_list' => '<list_code>'},
'javascript')
@db.view(@spec)
end

it "initialzes a view query with map/reduce/list funtions" do
@spec.stub(:design_document => 'design_doc', :view_name => 'my_view',
:map_function => '<map_code>', :reduce_function => '<reduce_code>',
:lib_function => nil, :list_name => 'my_list', :list_function => '<list_code>',
:language => 'javascript')
CouchPotato::View::ViewQuery.should_receive(:new).with(
@couchrest_db,
'design_doc',
{'my_view' => {
:map => '<map_code>',
:reduce => '<reduce_code>',
:lib => nil
}},
{'my_list' => '<list_code>'},
'javascript')
@db.view(@spec)
end

it "initialzes a view query with only map/reduce/lib functions" do
@spec.stub(:design_document => 'design_doc', :view_name => 'my_view',
:map_function => '<map_code>', :reduce_function => '<reduce_code>',
:list_name => nil, :list_function => nil,
:lib_function => {:test => '<test_code>'}).as_null_object
CouchPotato::View::ViewQuery.should_receive(:new).with(
@couchrest_db,
'design_doc',
{'my_view' => {
:map => '<map_code>',
:reduce => '<reduce_code>',
:lib => {:test => '<test_code>'}
}}, nil, anything)
@db.view(@spec)
end

it "initialzes a view query with only map/reduce functions" do
@spec.stub(:design_document => 'design_doc', :view_name => 'my_view',
:map_function => '<map_code>', :reduce_function => '<reduce_code>',
:list_name => nil, :list_function => nil).as_null_object
:lib_function => nil, :list_name => nil, :list_function => nil).as_null_object
CouchPotato::View::ViewQuery.should_receive(:new).with(
@couchrest_db,
'design_doc',
{'my_view' => {
:map => '<map_code>',
:reduce => '<reduce_code>'
:reduce => '<reduce_code>',
:lib => nil
}}, nil, anything)
@db.view(@spec)
end
Expand Down
42 changes: 26 additions & 16 deletions spec/unit/view_query_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
db = mock 'db', :get => nil, :view => nil

db.should_receive(:save_doc).with(
'views' => {'view' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}},
'views' => {'view' => {'map' => '<map_code>', 'reduce' => '<reduce_code>', 'lib' => {'test' => '<lib_code>'}}},
'lists' => {}, "_id" => "_design/design", "language" => "javascript")

CouchPotato::View::ViewQuery.new(db, 'design', :view => {:map => '<map_code>', :reduce => '<reduce_code>'}).query_view!
CouchPotato::View::ViewQuery.new(db, 'design', :view => {:map => '<map_code>', :reduce => '<reduce_code>', :lib => {'test' => "<lib_code>"}}).query_view!
end

it 'updates a view in erlang if it does not exist' do
Expand All @@ -34,9 +34,9 @@
end

it "does not update a view when the map/reduce functions haven't changed" do
db = mock 'db', :get => {'views' => {'view' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}}, :view => nil
db = mock 'db', :get => {'views' => {'view' => {'map' => '<map_code>', 'reduce' => '<reduce_code>', 'lib' => {'test' => '<lib_code>'}}}}, :view => nil
db.should_not_receive(:save_doc)
CouchPotato::View::ViewQuery.new(db, 'design', :view => {:map => '<map_code>', :reduce => '<reduce_code>'}).query_view!
CouchPotato::View::ViewQuery.new(db, 'design', :view => {:map => '<map_code>', :reduce => '<reduce_code>', :lib => {'test' => "<lib_code>"}}).query_view!
end

it "does not update a view when the list function hasn't changed" do
Expand All @@ -51,44 +51,54 @@
CouchPotato::View::ViewQuery.new(db, 'design', :view2 => {:map => '<new map_code>', :reduce => '<reduce_code>'}).query_view!
end

it "does not pass in a reduce key if there is no reduce function" do
db = mock 'db', :get => {'views' => {}}, :view => nil
it "updates a view when the map function has changed" do
db = mock 'db', :get => {'views' => {'view3' => {'map' => '<map_code>'}}}, :view => nil
db.should_receive(:save_doc)
CouchPotato::View::ViewQuery.new(db, 'design', :view3 => {:map => '<new map_code>'}).query_view!
end

db.should_receive(:save_doc).with('views' => {'view3' => {'map' => '<map code>'}})
it "does not update a view when the lib function hasn't changed" do
db = mock 'db', :get => {'views' => {'view' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}, 'lib' => {'test' => '<lib_code>'}}, :view => nil
db.should_not_receive(:save_doc)
CouchPotato::View::ViewQuery.new(db, 'design', {:view => {:map => '<map_code>', :reduce => '<reduce_code>'}}, :lib => {'test' => "<lib_code>"}).query_view!
end

CouchPotato::View::ViewQuery.new(db, 'design', :view3 => {:map => '<map code>', :reduce => nil}).query_view!
it "does not pass in a reduce or lib keys if there is no reduce function" do
db = mock 'db', :get => {'views' => {}}, :view => nil
db.should_receive(:save_doc).with('views' => {'view4' => {'map' => '<map code>'}})
CouchPotato::View::ViewQuery.new(db, 'design', :view4 => {:map => '<map code>', :reduce => nil}).query_view!
end

it "updates a view when the reduce function has changed" do
db = mock 'db', :get => {'views' => {'view4' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}}, :view => nil
db = mock 'db', :get => {'views' => {'view5' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}}, :view => nil
db.should_receive(:save_doc)
CouchPotato::View::ViewQuery.new(db, 'design', :view4 => {:map => '<map_code>', :reduce => '<new reduce_code>'}).query_view!
CouchPotato::View::ViewQuery.new(db, 'design', :view5 => {:map => '<map_code>', :reduce => '<new reduce_code>'}).query_view!
end

it "updates a view when the list function has changed" do
db = mock 'db', :get => {
'views' => {'view5' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}},
'views' => {'view6' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}},
'lists' => {'list1' => '<list_code>'}
}, :view => nil
db.should_receive(:save_doc)
CouchPotato::View::ViewQuery.new(db, 'design', {:view5 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, :list1 => '<new_list_code>').query_view!
CouchPotato::View::ViewQuery.new(db, 'design', {:view6 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, :list1 => '<new_list_code>').query_view!
end

it "updates a view when there wasn't a list function but now there is one" do
db = mock 'db', :get => {
'views' => {'view6' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}
'views' => {'view7' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}
}, :view => nil
db.should_receive(:save_doc)
CouchPotato::View::ViewQuery.new(db, 'design', {:view6 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, :list1 => '<new_list_code>').query_view!
CouchPotato::View::ViewQuery.new(db, 'design', {:view7 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, :list1 => '<new_list_code>').query_view!
end

it "does not update a view when there is a list function but no list function is passed" do
db = mock 'db', :get => {
'views' => {'view7' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}},
'views' => {'view8' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}},
'lists' => {'list1' => '<list_code>'}
}, :view => nil
db.should_not_receive(:save_doc)
CouchPotato::View::ViewQuery.new(db, 'design', {:view7 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, {}).query_view!
CouchPotato::View::ViewQuery.new(db, 'design', {:view8 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, {}).query_view!
end

it "does not update a view when there were no lists before and no list function is passed" do
Expand Down

0 comments on commit b464dd5

Please sign in to comment.