marbu 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. data/Rakefile +13 -0
  2. data/Readme.md +58 -0
  3. data/bin/marbu-web +20 -0
  4. data/bin/marbu-web-mongo-config.rb +8 -0
  5. data/lib/core_ext/array.rb +7 -0
  6. data/lib/core_ext/enumerable.rb +25 -0
  7. data/lib/core_ext/hash.rb +35 -0
  8. data/lib/core_ext/indifferent_access.rb +11 -0
  9. data/lib/core_ext/object.rb +25 -0
  10. data/lib/core_ext/open_struct.rb +3 -0
  11. data/lib/core_ext/string.rb +25 -0
  12. data/lib/marbu/builder.rb +48 -0
  13. data/lib/marbu/builders/mongodb.rb +106 -0
  14. data/lib/marbu/exceptions.rb +7 -0
  15. data/lib/marbu/formatters/base.rb +6 -0
  16. data/lib/marbu/formatters/dummy.rb +9 -0
  17. data/lib/marbu/formatters/formatters.rb +3 -0
  18. data/lib/marbu/formatters/one_line.rb +9 -0
  19. data/lib/marbu/models/db/db.rb +3 -0
  20. data/lib/marbu/models/db/mongodb/exceptions.rb +59 -0
  21. data/lib/marbu/models/db/mongodb/mongodb.rb +54 -0
  22. data/lib/marbu/models/db/mongodb/structure.rb +40 -0
  23. data/lib/marbu/models/exception_link.rb +11 -0
  24. data/lib/marbu/models/models.rb +3 -0
  25. data/lib/marbu/models/mrf/base.rb +133 -0
  26. data/lib/marbu/models/mrf/code.rb +32 -0
  27. data/lib/marbu/models/mrf/finalize.rb +9 -0
  28. data/lib/marbu/models/mrf/map.rb +7 -0
  29. data/lib/marbu/models/mrf/map_reduce_finalize.rb +107 -0
  30. data/lib/marbu/models/mrf/misc.rb +65 -0
  31. data/lib/marbu/models/mrf/mrf.rb +8 -0
  32. data/lib/marbu/models/mrf/query.rb +39 -0
  33. data/lib/marbu/models/mrf/reduce.rb +7 -0
  34. data/lib/marbu/server/public/css/style.css +149 -0
  35. data/lib/marbu/server/public/images/remove.png +0 -0
  36. data/lib/marbu/server/public/js/builder.js +200 -0
  37. data/lib/marbu/server/views/_builder_col_code.haml +8 -0
  38. data/lib/marbu/server/views/_builder_col_emit_keys.haml +13 -0
  39. data/lib/marbu/server/views/_builder_col_emit_values.haml +12 -0
  40. data/lib/marbu/server/views/_builder_data_samples.haml +8 -0
  41. data/lib/marbu/server/views/_builder_misc.haml +20 -0
  42. data/lib/marbu/server/views/_collection_nested_list.haml +0 -0
  43. data/lib/marbu/server/views/_footer.haml +2 -0
  44. data/lib/marbu/server/views/_header.haml +3 -0
  45. data/lib/marbu/server/views/_header_col.haml +6 -0
  46. data/lib/marbu/server/views/builder.haml +37 -0
  47. data/lib/marbu/server/views/layout.haml +19 -0
  48. data/lib/marbu/server/views/mapreduce.haml +9 -0
  49. data/lib/marbu/server/views/root.haml +11 -0
  50. data/lib/marbu/server/views/sample_data.haml +17 -0
  51. data/lib/marbu/server.rb +199 -0
  52. data/lib/marbu/server_sinatra.rb +168 -0
  53. data/lib/marbu/version.rb +3 -0
  54. data/lib/marbu.rb +65 -0
  55. data/spec/constants.rb +149 -0
  56. data/spec/rubymine-server.rb +0 -0
  57. data/spec/spec_helper.rb +63 -0
  58. data/spec/unit/builders/builder_spec.rb +5 -0
  59. data/spec/unit/builders/mongodb_spec.rb +52 -0
  60. data/spec/unit/models/base_spec.rb +33 -0
  61. data/spec/unit/models/map_reduce_finalize_spec.rb +28 -0
  62. data/spec/unit/models/map_spec.rb +22 -0
  63. data/spec/unit/models/query_spec.rb +23 -0
  64. metadata +209 -0
@@ -0,0 +1,168 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'sinatra'
4
+ require 'marbu'
5
+ Marbu.port = '27017'
6
+ Marbu.uri = '127.0.0.1'
7
+
8
+ Mongoid.configure do |config|
9
+ config.master = Mongo::Connection.new.db('marbu')
10
+ end
11
+
12
+ configure :development do
13
+ require 'ruby-debug'
14
+ enable :logging, :dump_errors, :raise_errors,
15
+ end
16
+
17
+ enable :method_override
18
+
19
+ dir = File.dirname(File.expand_path(__FILE__))
20
+ set :views, "#{dir}/server/views"
21
+ set :public_folder, "#{dir}/server/public"
22
+ set :static, true
23
+
24
+ helpers do
25
+ def url_path(*path_parts)
26
+ [ path_prefix, path_parts ].join("/").squeeze('/')
27
+ end
28
+ alias_method :u, :url_path
29
+
30
+ def path_prefix
31
+ request.env['SCRIPT_NAME']
32
+ end
33
+ end
34
+
35
+ get "/" do
36
+ @mrms = Marbu::Models::Db::MongoDb.all
37
+ show 'root'
38
+ end
39
+
40
+ get "/builder/new" do
41
+ @mrm = Marbu::Models::Db::MongoDb.new
42
+ @mrf = @mrm.map_reduce_finalize
43
+ show 'builder'
44
+ end
45
+
46
+ post "/builder" do
47
+ @mrm = build_mrm_from_params(params.merge({:logger => logger}))
48
+ @mrm.save!
49
+ redirect "/builder/#{@mrm.uuid}"
50
+ end
51
+
52
+ get "/builder/:uuid" do
53
+ @mrm = Marbu::Models::Db::MongoDb.first(conditions: {uuid: params['uuid']})
54
+ @mrf = @mrm.map_reduce_finalize
55
+ show 'builder'
56
+ end
57
+
58
+ put "/builder/:uuid" do
59
+ @mrm = build_mrm_from_params(params.merge({:logger => logger}))
60
+ @mrm.save!
61
+ redirect "/builder/#{@mrm.uuid}"
62
+ end
63
+
64
+ delete "/builder/:uuid" do
65
+ @mrm = Marbu::Models::Db::MongoDb.first(conditions: {uuid: params['uuid']})
66
+ @mrm.destroy if @mrm.present?
67
+ redirect "/"
68
+ end
69
+
70
+ get "/mapreduce/:uuid" do
71
+ @mrm = Marbu::Models::Db::MongoDb.first(conditions: {uuid: params['uuid']})
72
+ @mrf = @mrm.map_reduce_finalize
73
+ @builder = Marbu::Builder.new(@mrf)
74
+ @error = nil
75
+
76
+ begin
77
+ # TODO: naturally this has to take the DATABASE and COLLECTION from the mapreducefilter object
78
+ # TODO: don;t take the parameters from the mapreducefilter object if DATABASE or DATABASE and COLLECTION are
79
+ # TODo: defined in the configuration (security)
80
+ @res = @mrf.misc.collection.map_reduce( @builder.map(:mongodb), @builder.reduce(:mongodb),
81
+ {
82
+ :query => @builder.query,
83
+ :out => {:replace => "tmp."+@mrm.map_reduce_finalize.misc.output_collection},
84
+ :finalize => @builder.finalize(:mongodb)
85
+ }
86
+ )
87
+ rescue Mongo::OperationFailure => e
88
+ @parsed_error = Marbu::Models::Db::MongoDb::Exception.explain(e, @mrf)
89
+ @error = @parsed_error[:message]
90
+ @fix_link = Marbu::Models::ExceptionLink.get_exception_fix_link(@parsed_error[:id], params['uuid'])
91
+ end
92
+
93
+ show 'mapreduce'
94
+ end
95
+
96
+ def build_mrm_from_params(params)
97
+ name = 'name'
98
+ function = 'function'
99
+
100
+ if (uuid = params['uuid'])
101
+ mrm = Marbu::Models::Db::MongoDb.find_or_create_by(uuid: uuid)
102
+ else
103
+ mrm = Marbu::Models::Db::MongoDb.new
104
+ end
105
+ mrm.name = params['name']
106
+ mrf = mrm.map_reduce_finalize
107
+
108
+ mrf.map = Marbu::Models::Map.new(
109
+ :code => {:text => params['map_code']}
110
+ )
111
+ mrf.reduce = Marbu::Models::Reduce.new(
112
+ :code => {:text => params['reduce_code']}
113
+ )
114
+ mrf.finalize = Marbu::Models::Finalize.new(
115
+ :code => {:text => params['finalize_code']}
116
+ )
117
+ mrf.query = Marbu::Models::Query.new(
118
+ :condition => params['query_condition'],
119
+ :force_query => params['query_force_query']
120
+ )
121
+ mrf.misc = Marbu::Models::Misc.new(
122
+ :database => params['database'],
123
+ :input_collection => params['input_collection'],
124
+ :output_collection => params['output_collection']
125
+ )
126
+
127
+ # add params to map_new, reduce_new, finalize_new
128
+ ['map', 'reduce', 'finalize'].each do |stage|
129
+ ['key', 'value'].each do |type|
130
+ stage_type_name = params["#{stage}_#{type}_#{name}"]
131
+ stage_type_function = params["#{stage}_#{type}_#{function}"]
132
+
133
+ if( stage_type_name.present?)
134
+ stage_type_name.each_with_index do |n, i|
135
+ case stage
136
+ when 'map' then add(mrf.map, type, n, stage_type_function[i])
137
+ when 'reduce' then add(mrf.reduce, type, n, stage_type_function[i])
138
+ when 'finalize' then add(mrf.finalize, type, n, stage_type_function[i])
139
+ else raise Exception.new("#{stage} in #{k} is unknown")
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+
146
+ # TODO:
147
+ # copy keys and values from map to reduce block
148
+ # copy keys from map to finalize block
149
+ # reduce_new.keys = mrf.map.keys
150
+ # reduce_new.values = mrf.map.values
151
+ # finalize_new.keys = mrf.map.keys
152
+
153
+ mrm.map_reduce_finalize = mrf
154
+ return mrm
155
+ end
156
+
157
+ def add(model, type, name, function)
158
+ case type
159
+ when 'key' then model.add_key(name, function)
160
+ when 'value' then model.add_value(name, function)
161
+ else raise Exception.new("#{type} is unknown")
162
+ end
163
+ end
164
+
165
+ def show(page)
166
+ haml page.to_sym
167
+ end
168
+
@@ -0,0 +1,3 @@
1
+ module Marbu
2
+ VERSION = "0.1.0"
3
+ end
data/lib/marbu.rb ADDED
@@ -0,0 +1,65 @@
1
+ require 'mongo'
2
+ require 'mongoid'
3
+ require 'core_ext/enumerable'
4
+
5
+ require 'marbu/exceptions'
6
+ require 'marbu/formatters/formatters'
7
+ require 'marbu/builders/mongodb'
8
+ require 'marbu/builder'
9
+ require 'marbu/models/models'
10
+
11
+ module Marbu
12
+ # Your code goes here...
13
+ extend self
14
+
15
+ attr_reader :port, :uri
16
+ attr_accessor :storage
17
+
18
+ def database=(database)
19
+ @database = database
20
+ end
21
+
22
+ def collection=(collection)
23
+ @collection = collection
24
+ end
25
+
26
+ def port=(port)
27
+ @port = port
28
+ end
29
+
30
+ def uri=(uri)
31
+ @uri = uri
32
+ end
33
+
34
+ def connection
35
+ if( @uri and @port )
36
+ @connection ||= Mongo::Connection.new(@uri, @port)
37
+ else
38
+ @connection = nil
39
+ end
40
+
41
+ @connection
42
+ end
43
+
44
+ def database
45
+ if connection and @database
46
+ connection.db(@database)
47
+ else
48
+ nil
49
+ end
50
+ end
51
+
52
+ def collection
53
+ if database and @collection
54
+ database.collection(@collection)
55
+ else
56
+ nil
57
+ end
58
+ end
59
+
60
+ def storage_collection
61
+ Mongo::Connection.new(storage[:uri],storage[:port]).db(storage[:database]).collection(storage[:collection])
62
+ end
63
+ end
64
+
65
+
data/spec/constants.rb ADDED
@@ -0,0 +1,149 @@
1
+ MR_WWB_LOC_DIM0 = {
2
+ :map => {
3
+ :keys => [
4
+ {:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"}
5
+ ],
6
+ :values => [
7
+ {:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
8
+ {:name => "count"}
9
+ ],
10
+ :code => {
11
+ :text => 'count = 1;',
12
+ :type => "JS"
13
+ }
14
+ },
15
+
16
+ :reduce => {
17
+ :values => [
18
+ {:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
19
+ {:name => "count"}
20
+ ],
21
+ :code => {
22
+ :type => "JS",
23
+ :text => <<-JS
24
+ var count = 0;
25
+ values.forEach(function(v){
26
+ count += v.count;
27
+ });
28
+ JS
29
+ }
30
+ },
31
+
32
+ :finalize => {
33
+ :values => [
34
+ {:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
35
+ {:name => "count", :function => "value.count"}
36
+ ],
37
+ :code => {
38
+ :text => 'count = (count/100)*100.0;',
39
+ :type => "JS"
40
+ }
41
+ },
42
+
43
+ :misc => {
44
+ :database => "qed_test",
45
+ :input_collection => 'world_wide_business',
46
+ :output_collection => 'world_wide_business_mr_dim0',
47
+ :output_operation => 'replace',
48
+ :filter_data => true,
49
+ },
50
+
51
+ :query => {
52
+ :datetime_fields => [:created_at]
53
+ }
54
+ }
55
+
56
+ MR_WWB_LOC_DIM0_NO_MAP_EMIT_KEYS = {
57
+ :map => {
58
+ :values => [
59
+ {:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
60
+ {:name => "count"}
61
+ ],
62
+ :code => {
63
+ :text => 'count = 1;',
64
+ :type => "JSS"
65
+ }
66
+ },
67
+
68
+ :reduce => {
69
+ :code => {
70
+ :text => <<-JS
71
+ var count = 0;
72
+ values.forEach(function(v){
73
+ count += v.count;
74
+ });
75
+ JS
76
+ }
77
+ },
78
+
79
+ :finalize => {
80
+ :values => [
81
+ {:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
82
+ {:name => "count", :function => "value.count"}
83
+ ],
84
+ :code => {
85
+ :type => "JS",
86
+ :text => 'count = (count/100)*100.0;',
87
+ }
88
+ },
89
+
90
+ :misc => {
91
+ :database => "qed_test",
92
+ :input_collection => 'world_wide_business',
93
+ :output_collection => 'world_wide_business_mr_dim0',
94
+ },
95
+
96
+ :query => {
97
+ :datetime_fields => [:created_at]
98
+ }
99
+ }
100
+
101
+ MR_WWB_LOC_DIM0_TWO_MAP_EMIT_KEYS = {
102
+ :map => {
103
+ :keys => [
104
+ {:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
105
+ {:name => "DIM_LOC_1", :function => "value.DIM_LOC_1"}
106
+ ],
107
+ :values => [
108
+ {:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
109
+ {:name => "count"}
110
+ ],
111
+ :code => {
112
+ :text => 'count = 1;',
113
+ :type => "JS"
114
+ }
115
+ },
116
+
117
+ :reduce => {
118
+ :code => {
119
+ :type => "JS",
120
+ :text => <<-JS
121
+ var count = 0;
122
+ values.forEach(function(v){
123
+ count += v.count;
124
+ });
125
+ JS
126
+ }
127
+ },
128
+
129
+ :finalize => {
130
+ :values => [
131
+ {:name => "DIM_LOC_0", :function => "value.DIM_LOC_0"},
132
+ {:name => "count", :function => "value.count"}
133
+ ],
134
+ :code => {
135
+ :text => 'count = (count/100)*100.0;',
136
+ :type => "JS"
137
+ }
138
+ },
139
+
140
+ :misc => {
141
+ :database => "qed_test",
142
+ :input_collection => 'world_wide_business',
143
+ :output_collection => 'world_wide_business_mr_dim0',
144
+ },
145
+
146
+ :query => {
147
+ :datetime_fields => [:created_at]
148
+ }
149
+ }
File without changes
@@ -0,0 +1,63 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter "/spec/"
4
+ end
5
+
6
+ require 'rubygems'
7
+ require 'spork'
8
+
9
+ Spork.prefork do
10
+ # Loading more in this block will cause your tests to run faster. However,
11
+ # if you change any configuration or code from libraries loaded here, you'll
12
+ # need to restart spork for it take effect.
13
+
14
+ end
15
+
16
+ Spork.each_run do
17
+ # This code will be run each time you run your specs.
18
+
19
+ end
20
+
21
+ # --- Instructions ---
22
+ # Sort the contents of this file into a Spork.prefork and a Spork.each_run
23
+ # block.
24
+ #
25
+ # The Spork.prefork block is run only once when the spork server is started.
26
+ # You typically want to place most of your (slow) initializer code in here, in
27
+ # particular, require'ing any 3rd-party gems that you don't normally modify
28
+ # during development.
29
+ #
30
+ # The Spork.each_run block is run each time you run your specs. In case you
31
+ # need to load files that tend to change during development, require them here.
32
+ # With Rails, your application modules are loaded automatically, so sometimes
33
+ # this block can remain empty.
34
+ #
35
+ # Note: You can modify files loaded *from* the Spork.each_run block without
36
+ # restarting the spork server. However, this file itself will not be reloaded,
37
+ # so if you change any of the code inside the each_run block, you still need to
38
+ # restart the server. In general, if you have non-trivial code in this file,
39
+ # it's advisable to move it into a separate file so you can easily edit it
40
+ # without restarting spork. (For example, with RSpec, you could move
41
+ # non-trivial code into a file spec/support/my_helper.rb, making sure that the
42
+ # spec/support/* files are require'd from inside the each_run block.)
43
+ #
44
+ # Any code that is left outside the two blocks will be run during preforking
45
+ # *and* during each_run -- that's probably not what you want.
46
+ #
47
+ # These instructions should self-destruct in 10 seconds. If they don't, feel
48
+ # free to delete them.
49
+
50
+
51
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
52
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
53
+
54
+ require 'marbu'
55
+ require 'rspec'
56
+ require 'factory_girl'
57
+ require 'constants'
58
+ require 'mongodb-testdata-factory'
59
+ FactoryGirl.find_definitions
60
+
61
+ RSpec.configure do |config|
62
+ config.include Factory::Syntax::Methods
63
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Marbu::Builder do
4
+
5
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ MONGODB_MAP_FUNCTION_ONE_LINE =
4
+ "function(){value=this.value;count=1;emit({DIM_LOC_0:value.DIM_LOC_0},{DIM_LOC_0:value.DIM_LOC_0,count:count});}"
5
+ MONGODB_MAP_FUNCTION_TWO_EMIT_KEYS_ONE_LINE =
6
+ "function(){value=this.value;count=1;emit({DIM_LOC_0:value.DIM_LOC_0,DIM_LOC_1:value.DIM_LOC_1},{DIM_LOC_0:value.DIM_LOC_0,count:count});}"
7
+ MONGODB_REDUCE_FUNCTION_ONE_LINE =
8
+ "function(key,values){value=values[0];varcount=0;values.forEach(function(v){count+=v.count;});return{DIM_LOC_0:value.DIM_LOC_0,count:count};}"
9
+ MONGODB_FINALIZE_FUNCTION_ONE_LINE =
10
+ "function(key,value){count=(count/100)*100.0;return{DIM_LOC_0:value.DIM_LOC_0,count:value.count};}"
11
+
12
+ describe Marbu::Builder::Mongodb do
13
+ context "for a mapreduce with one emit key" do
14
+ let(:mrf) { Marbu::Models::MapReduceFinalize.new(MR_WWB_LOC_DIM0) }
15
+
16
+ it "creates a map query" do
17
+ Marbu::Builder::Mongodb.map(mrf.map).should_not be_empty
18
+ end
19
+
20
+ it 'creates the correct map query' do
21
+ Marbu::Formatter::OneLine.perform(Marbu::Builder::Mongodb.map(mrf.map)).should == MONGODB_MAP_FUNCTION_ONE_LINE
22
+ end
23
+
24
+ it "creates a reduce query" do
25
+ Marbu::Builder::Mongodb.reduce(mrf.reduce).should_not be_empty
26
+ end
27
+
28
+ it 'creates the correct reduce query' do
29
+ Marbu::Formatter::OneLine.perform(Marbu::Builder::Mongodb.reduce(mrf.reduce)).should == MONGODB_REDUCE_FUNCTION_ONE_LINE
30
+ end
31
+
32
+ it "creates a finalize query" do
33
+ Marbu::Builder::Mongodb.finalize(mrf.finalize).should_not be_empty
34
+ end
35
+
36
+ it 'create the correct finalize query' do
37
+ Marbu::Formatter::OneLine.perform(Marbu::Builder::Mongodb.finalize(mrf.finalize)).should == MONGODB_FINALIZE_FUNCTION_ONE_LINE
38
+ end
39
+ end
40
+
41
+ context "for a mapreduce with at least two emit keys" do
42
+ let(:mrf) { Marbu::Models::MapReduceFinalize.new(MR_WWB_LOC_DIM0_TWO_MAP_EMIT_KEYS) }
43
+
44
+ it "creates a map query" do
45
+ Marbu::Builder::Mongodb.map(mrf.map).should_not be_empty
46
+ end
47
+
48
+ it 'creates the correct map query' do
49
+ Marbu::Formatter::OneLine.perform(Marbu::Builder::Mongodb.map(mrf.map)).should == MONGODB_MAP_FUNCTION_TWO_EMIT_KEYS_ONE_LINE
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Marbu::Models::Base do
4
+ context "a new Base instace" do
5
+ let(:base) { Marbu::Models::Base.new }
6
+ let(:modified_key_in_function) { 'value.key' }
7
+
8
+ it "can be added a key without a function" do
9
+ base.add_key('some_key')
10
+
11
+ base.keys.first.name.should == 'some_key'
12
+ base.keys.first.function.should == 'value.some_key'
13
+ end
14
+
15
+ it "can be added an emit key with a function" do
16
+ base.add_key('some_key', 'some_function')
17
+
18
+ base.keys.size.should == 1
19
+ key = base.keys.first
20
+ key.name.should == 'some_key'
21
+ key.function.should == 'some_function'
22
+ end
23
+
24
+ # it "adds an emit_key with add_key(key)" do
25
+ # # base.add_key(@key)
26
+ # #
27
+ # # base.keys.size.should == 1
28
+ # # key = base.keys.first
29
+ # # key.name.should == @key
30
+ # # key.function.should == @modified_key_in_function
31
+ # end
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Marbu::Models::MapReduceFinalize do
4
+
5
+ context "when instantiated with no params" do
6
+ let(:mrf) { Marbu::Models::MapReduceFinalize.new }
7
+
8
+ it "has a map" do
9
+ mrf.map.should be_an_instance_of(Marbu::Models::Map)
10
+ end
11
+
12
+ it "has a reduce" do
13
+ mrf.reduce.should be_an_instance_of(Marbu::Models::Reduce)
14
+ end
15
+
16
+ it "has a finalize" do
17
+ mrf.finalize.should be_an_instance_of(Marbu::Models::Finalize)
18
+ end
19
+ end
20
+
21
+ context "when instantiated with a valid params hash" do
22
+ let(:mrf) { Marbu::Models::MapReduceFinalize.new(MR_WWB_LOC_DIM0) }
23
+
24
+ it "return the serializable hash" do
25
+ mrf.serializable_hash.should == MR_WWB_LOC_DIM0
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe Marbu::Models::Map do
4
+ context "when instantiated with empty parameters" do
5
+ let(:map) do
6
+ Marbu::Models::Map.new
7
+ end
8
+
9
+ it "should have no keys" do
10
+ map.keys.should be_empty
11
+ end
12
+
13
+ it "should have no values" do
14
+ map.values.should be_empty
15
+ end
16
+
17
+ it "should have no code" do
18
+ map.code.present?.should be_false
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Marbu::Models::Query do
4
+ context "a new Query instace" do
5
+ let(:query) { Marbu::Models::Query.new }
6
+
7
+ it "returns false for present?" do
8
+ query.present?.should be_false
9
+ end
10
+
11
+ context "with at least one attribute set" do
12
+ it "returns true for present? with attribute condition set" do
13
+ query.condition = 'abc'
14
+ query.present?.should be_true
15
+ end
16
+
17
+ it "returns true for present? with attribute datetime_fields set" do
18
+ query.datetime_fields = ['abc']
19
+ query.present?.should be_true
20
+ end
21
+ end
22
+ end
23
+ end