couch_potato-rails2 0.5.6
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.
- data/.gitignore +7 -0
- data/.travis.yml +5 -0
- data/CHANGES.md +148 -0
- data/CREDITS +6 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.md +450 -0
- data/Rakefile +82 -0
- data/couch_potato.gemspec +27 -0
- data/init.rb +3 -0
- data/lib/core_ext/date.rb +14 -0
- data/lib/core_ext/object.rb +5 -0
- data/lib/core_ext/string.rb +12 -0
- data/lib/core_ext/symbol.rb +15 -0
- data/lib/core_ext/time.rb +23 -0
- data/lib/couch_potato.rb +48 -0
- data/lib/couch_potato/database.rb +179 -0
- data/lib/couch_potato/persistence.rb +124 -0
- data/lib/couch_potato/persistence/active_model_compliance.rb +44 -0
- data/lib/couch_potato/persistence/attachments.rb +31 -0
- data/lib/couch_potato/persistence/callbacks.rb +29 -0
- data/lib/couch_potato/persistence/dirty_attributes.rb +56 -0
- data/lib/couch_potato/persistence/ghost_attributes.rb +12 -0
- data/lib/couch_potato/persistence/json.rb +47 -0
- data/lib/couch_potato/persistence/magic_timestamps.rb +23 -0
- data/lib/couch_potato/persistence/properties.rb +79 -0
- data/lib/couch_potato/persistence/simple_property.rb +82 -0
- data/lib/couch_potato/persistence/type_caster.rb +40 -0
- data/lib/couch_potato/railtie.rb +25 -0
- data/lib/couch_potato/rspec.rb +2 -0
- data/lib/couch_potato/rspec/matchers.rb +39 -0
- data/lib/couch_potato/rspec/matchers/json2.js +482 -0
- data/lib/couch_potato/rspec/matchers/list_as_matcher.rb +54 -0
- data/lib/couch_potato/rspec/matchers/map_to_matcher.rb +49 -0
- data/lib/couch_potato/rspec/matchers/print_r.js +60 -0
- data/lib/couch_potato/rspec/matchers/reduce_to_matcher.rb +50 -0
- data/lib/couch_potato/rspec/stub_db.rb +46 -0
- data/lib/couch_potato/validation.rb +16 -0
- data/lib/couch_potato/validation/with_active_model.rb +27 -0
- data/lib/couch_potato/validation/with_validatable.rb +41 -0
- data/lib/couch_potato/version.rb +3 -0
- data/lib/couch_potato/view/base_view_spec.rb +84 -0
- data/lib/couch_potato/view/custom_view_spec.rb +42 -0
- data/lib/couch_potato/view/custom_views.rb +52 -0
- data/lib/couch_potato/view/lists.rb +23 -0
- data/lib/couch_potato/view/model_view_spec.rb +75 -0
- data/lib/couch_potato/view/properties_view_spec.rb +47 -0
- data/lib/couch_potato/view/raw_view_spec.rb +25 -0
- data/lib/couch_potato/view/view_query.rb +82 -0
- data/rails/init.rb +4 -0
- data/rails/reload_classes.rb +47 -0
- data/spec/attachments_spec.rb +23 -0
- data/spec/callbacks_spec.rb +297 -0
- data/spec/create_spec.rb +35 -0
- data/spec/custom_view_spec.rb +239 -0
- data/spec/default_property_spec.rb +38 -0
- data/spec/destroy_spec.rb +29 -0
- data/spec/fixtures/address.rb +10 -0
- data/spec/fixtures/person.rb +6 -0
- data/spec/property_spec.rb +323 -0
- data/spec/rails_spec.rb +50 -0
- data/spec/railtie_spec.rb +65 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/unit/active_model_compliance_spec.rb +98 -0
- data/spec/unit/attributes_spec.rb +135 -0
- data/spec/unit/base_view_spec_spec.rb +106 -0
- data/spec/unit/callbacks_spec.rb +46 -0
- data/spec/unit/couch_potato_spec.rb +39 -0
- data/spec/unit/create_spec.rb +69 -0
- data/spec/unit/custom_views_spec.rb +15 -0
- data/spec/unit/database_spec.rb +317 -0
- data/spec/unit/date_spec.rb +22 -0
- data/spec/unit/dirty_attributes_spec.rb +136 -0
- data/spec/unit/initialize_spec.rb +38 -0
- data/spec/unit/json_spec.rb +30 -0
- data/spec/unit/lists_spec.rb +20 -0
- data/spec/unit/model_view_spec_spec.rb +13 -0
- data/spec/unit/properties_view_spec_spec.rb +31 -0
- data/spec/unit/rspec_matchers_spec.rb +124 -0
- data/spec/unit/rspec_stub_db_spec.rb +35 -0
- data/spec/unit/string_spec.rb +7 -0
- data/spec/unit/time_spec.rb +15 -0
- data/spec/unit/validation_spec.rb +67 -0
- data/spec/unit/view_query_spec.rb +86 -0
- data/spec/update_spec.rb +40 -0
- data/spec/view_updates_spec.rb +28 -0
- metadata +243 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
module CouchPotato
|
2
|
+
module RSpec
|
3
|
+
class ListAsProxy
|
4
|
+
def initialize(results_ruby)
|
5
|
+
@results_ruby = results_ruby
|
6
|
+
end
|
7
|
+
|
8
|
+
def as(expected_ruby)
|
9
|
+
ListAsMatcher.new(expected_ruby, @results_ruby)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class ListAsMatcher
|
14
|
+
include RunJS
|
15
|
+
|
16
|
+
def initialize(expected_ruby, results_ruby)
|
17
|
+
@expected_ruby = expected_ruby
|
18
|
+
@results_ruby = results_ruby
|
19
|
+
end
|
20
|
+
|
21
|
+
def matches?(view_spec)
|
22
|
+
js = <<-JS
|
23
|
+
#{File.read(File.dirname(__FILE__) + '/print_r.js')}
|
24
|
+
#{File.read(File.dirname(__FILE__) + '/json2.js')}
|
25
|
+
var results = #{@results_ruby.to_json};
|
26
|
+
var listed = '';
|
27
|
+
var list = #{view_spec.list_function};
|
28
|
+
|
29
|
+
var getRow = function() {
|
30
|
+
return results.rows.shift();
|
31
|
+
};
|
32
|
+
var send = function(text) {
|
33
|
+
listed = listed + text;
|
34
|
+
};
|
35
|
+
list();
|
36
|
+
print(print_r(JSON.parse(listed)));
|
37
|
+
JS
|
38
|
+
|
39
|
+
@actual_ruby = JSON.parse(run_js(js))
|
40
|
+
|
41
|
+
@expected_ruby == @actual_ruby
|
42
|
+
end
|
43
|
+
|
44
|
+
def failure_message_for_should
|
45
|
+
"Expected to list as #{@expected_ruby.inspect} but got #{@actual_ruby.inspect}."
|
46
|
+
end
|
47
|
+
|
48
|
+
def failure_message_for_should_not
|
49
|
+
"Expected to not list as #{@expected_ruby.inspect} but did."
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
|
4
|
+
module CouchPotato
|
5
|
+
module RSpec
|
6
|
+
class MapToProxy
|
7
|
+
def initialize(input_ruby)
|
8
|
+
@input_ruby = input_ruby
|
9
|
+
end
|
10
|
+
|
11
|
+
def to(*expected_ruby)
|
12
|
+
MapToMatcher.new(expected_ruby, @input_ruby)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class MapToMatcher
|
17
|
+
include RunJS
|
18
|
+
|
19
|
+
def initialize(expected_ruby, input_ruby)
|
20
|
+
@expected_ruby = expected_ruby
|
21
|
+
@input_ruby = input_ruby
|
22
|
+
end
|
23
|
+
|
24
|
+
def matches?(view_spec)
|
25
|
+
js = <<-JS
|
26
|
+
#{File.read(File.dirname(__FILE__) + '/print_r.js')}
|
27
|
+
var doc = #{@input_ruby.to_json};
|
28
|
+
var map = #{view_spec.map_function};
|
29
|
+
var result = [];
|
30
|
+
var emit = function(key, value) {
|
31
|
+
result.push([key, value]);
|
32
|
+
};
|
33
|
+
map(doc);
|
34
|
+
print(print_r(result));
|
35
|
+
JS
|
36
|
+
@actual_ruby = JSON.parse(run_js(js))
|
37
|
+
@expected_ruby == @actual_ruby
|
38
|
+
end
|
39
|
+
|
40
|
+
def failure_message_for_should
|
41
|
+
"Expected to map to #{@expected_ruby.inspect} but got #{@actual_ruby.inspect}."
|
42
|
+
end
|
43
|
+
|
44
|
+
def failure_message_for_should_not
|
45
|
+
"Expected not to map to #{@actual_ruby.inspect} but did."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
// taken and adapted from http://scriptnode.com/article/javascript-print_r-or-var_dump-equivalent/
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Concatenates the values of a variable into an easily readable string
|
5
|
+
* by Matt Hackett [scriptnode.com]
|
6
|
+
* @param {Object} x The variable to debug
|
7
|
+
* @param {Number} max The maximum number of recursions allowed (keep low, around 5 for HTML elements to prevent errors) [default: 10]
|
8
|
+
* @param {String} sep The separator to use between [default: a single space ' ']
|
9
|
+
* @param {Number} l The current level deep (amount of recursion). Do not use this parameter: it's for the function's own use
|
10
|
+
*/
|
11
|
+
function print_r(x, max, sep, l) {
|
12
|
+
|
13
|
+
l = l || 0;
|
14
|
+
max = max || 10;
|
15
|
+
sep = sep || ' ';
|
16
|
+
|
17
|
+
if (l > max) {
|
18
|
+
throw("Too much recursion");
|
19
|
+
};
|
20
|
+
|
21
|
+
var r = '';
|
22
|
+
|
23
|
+
if (x === null) {
|
24
|
+
r += "null";
|
25
|
+
} else if (is_array(x)) {
|
26
|
+
r += '[' + x.map(function(i) {
|
27
|
+
return print_r(i, max, sep, (l + 1));
|
28
|
+
}).join(', ') + ']';
|
29
|
+
} else if(is_object(x)) {
|
30
|
+
r += '{'
|
31
|
+
var pairs = [];
|
32
|
+
for (i in x) {
|
33
|
+
pairs.push('"' + i + '": ' + print_r(x[i], max, sep, (l + 1)));
|
34
|
+
}
|
35
|
+
r += pairs.join(', ');
|
36
|
+
r += '}';
|
37
|
+
} else if(is_string(x)) {
|
38
|
+
r += '"' + x + "\"";
|
39
|
+
} else {
|
40
|
+
r += x;
|
41
|
+
};
|
42
|
+
|
43
|
+
return r;
|
44
|
+
|
45
|
+
function is_string(a) {
|
46
|
+
return typeof a === 'string';
|
47
|
+
};
|
48
|
+
|
49
|
+
function is_array(a) {
|
50
|
+
return (a &&
|
51
|
+
typeof a === 'object' &&
|
52
|
+
a.constructor === Array);
|
53
|
+
};
|
54
|
+
|
55
|
+
function is_object(a) {
|
56
|
+
return a && typeof a == 'object'
|
57
|
+
};
|
58
|
+
|
59
|
+
};
|
60
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module CouchPotato
|
2
|
+
module RSpec
|
3
|
+
class ReduceToProxy
|
4
|
+
def initialize(docs, keys, rereduce = false)
|
5
|
+
@docs, @keys, @rereduce = docs, keys, rereduce
|
6
|
+
end
|
7
|
+
|
8
|
+
def to(expected_ruby)
|
9
|
+
ReduceToMatcher.new(expected_ruby, @docs, @keys, @rereduce)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class ReduceToMatcher
|
14
|
+
include RunJS
|
15
|
+
|
16
|
+
def initialize(expected_ruby, docs, keys, rereduce = false)
|
17
|
+
@expected_ruby, @docs, @keys, @rereduce = expected_ruby, docs, keys, rereduce
|
18
|
+
end
|
19
|
+
|
20
|
+
def matches?(view_spec)
|
21
|
+
js = <<-JS
|
22
|
+
#{File.read(File.dirname(__FILE__) + '/print_r.js')}
|
23
|
+
|
24
|
+
sum = function(values) {
|
25
|
+
var rv = 0;
|
26
|
+
for (var i in values) {
|
27
|
+
rv += values[i];
|
28
|
+
}
|
29
|
+
return rv;
|
30
|
+
};
|
31
|
+
|
32
|
+
var docs = #{@docs.to_json};
|
33
|
+
var keys = #{@keys.to_json};
|
34
|
+
var reduce = #{view_spec.reduce_function};
|
35
|
+
print(print_r({result: reduce(docs, keys, #{@rereduce})}));
|
36
|
+
JS
|
37
|
+
@actual_ruby = JSON.parse(run_js(js))['result']
|
38
|
+
@expected_ruby == @actual_ruby
|
39
|
+
end
|
40
|
+
|
41
|
+
def failure_message_for_should
|
42
|
+
"Expected to reduce to #{@expected_ruby.inspect} but got #{@actual_ruby.inspect}."
|
43
|
+
end
|
44
|
+
|
45
|
+
def failure_message_for_should_not
|
46
|
+
"Expected not to reduce to #{@actual_ruby.inspect} but did."
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module CouchPotato::RSpec
|
2
|
+
|
3
|
+
module StubView
|
4
|
+
class ViewStub
|
5
|
+
def initialize(clazz, view, db)
|
6
|
+
@clazz = clazz
|
7
|
+
@view = view
|
8
|
+
@db = db
|
9
|
+
end
|
10
|
+
|
11
|
+
def with(*args)
|
12
|
+
@args = args
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
def and_return(return_value)
|
17
|
+
view_stub = RSpec::Mocks::Mock.new("#{@clazz}.#{@view}(#{@args.try(:join, ', ')}) view")
|
18
|
+
_stub = @clazz.stub(@view)
|
19
|
+
_stub.with(*@args) if @args
|
20
|
+
_stub.and_return(view_stub)
|
21
|
+
@db.stub(:view).with(view_stub).and_return(return_value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def stub_view(clazz, view)
|
26
|
+
ViewStub.new clazz, view, self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module StubDb
|
31
|
+
def stub_db(options = {})
|
32
|
+
db = stub('db', options)
|
33
|
+
db.extend CouchPotato::RSpec::StubView
|
34
|
+
CouchPotato.stub(:database => db)
|
35
|
+
db
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module RSpec
|
41
|
+
module Mocks
|
42
|
+
module ExampleMethods
|
43
|
+
include CouchPotato::RSpec::StubDb
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module CouchPotato
|
2
|
+
module Validation
|
3
|
+
def self.included(base) #:nodoc:
|
4
|
+
case CouchPotato::Config.validation_framework
|
5
|
+
when :validatable
|
6
|
+
require 'couch_potato/validation/with_validatable'
|
7
|
+
base.send :include, CouchPotato::Validation::WithValidatable
|
8
|
+
when :active_model
|
9
|
+
require 'couch_potato/validation/with_active_model'
|
10
|
+
base.send :include, CouchPotato::Validation::WithActiveModel
|
11
|
+
else
|
12
|
+
raise "Unknown CouchPotato::Config.validation_framework #{CouchPotato::Config.validation_framework.inspect}, options are :validatable or :active_model"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module CouchPotato
|
2
|
+
module Validation
|
3
|
+
module WithActiveModel
|
4
|
+
def self.included(base)
|
5
|
+
require 'active_model'
|
6
|
+
require 'active_model/translation'
|
7
|
+
base.send :include, ::ActiveModel::Validations
|
8
|
+
base.instance_eval do
|
9
|
+
def before_validation(*names)
|
10
|
+
names.each do |name|
|
11
|
+
validate name
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# provide same interface to errors object as in Validatable
|
21
|
+
module ::ActiveModel
|
22
|
+
class Errors
|
23
|
+
def errors
|
24
|
+
self
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module CouchPotato
|
2
|
+
module Validation
|
3
|
+
module WithValidatable
|
4
|
+
def self.included(base)
|
5
|
+
begin
|
6
|
+
require 'validatable'
|
7
|
+
rescue LoadError
|
8
|
+
puts "Please install the gem validatable using 'gem install validatable'"
|
9
|
+
raise
|
10
|
+
end
|
11
|
+
base.send :include, ::Validatable
|
12
|
+
base.class_eval do
|
13
|
+
# Override the validate method to first run before_validation callback
|
14
|
+
def valid_with_before_validation_callback?
|
15
|
+
errors.clear
|
16
|
+
run_callbacks :validation do
|
17
|
+
before_validation_errors = errors.errors.dup
|
18
|
+
valid_without_before_validation_callback?
|
19
|
+
before_validation_errors.each do |k, v|
|
20
|
+
v.each {|message| errors.add(k, message)}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
errors.empty?
|
24
|
+
end
|
25
|
+
|
26
|
+
alias_method :valid_without_before_validation_callback?, :valid?
|
27
|
+
alias_method :valid?, :valid_with_before_validation_callback?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# add [] method to Validatable's implementation of the Errors class
|
35
|
+
module Validatable
|
36
|
+
class Errors
|
37
|
+
def [](attribute)
|
38
|
+
[on(attribute)].flatten.compact
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module CouchPotato
|
2
|
+
module View
|
3
|
+
class BaseViewSpec
|
4
|
+
attr_reader :reduce_function, :list_name, :list_function, :design_document, :view_name, :view_parameters, :klass, :options
|
5
|
+
private :klass, :options
|
6
|
+
|
7
|
+
def initialize(klass, view_name, options, view_parameters)
|
8
|
+
normalized_view_parameters = normalize_view_parameters view_parameters
|
9
|
+
|
10
|
+
@list_name = normalized_view_parameters.delete(:list) || options[:list]
|
11
|
+
|
12
|
+
assert_valid_view_parameters normalized_view_parameters
|
13
|
+
@klass = klass
|
14
|
+
@design_document = translate_to_design_doc_name(klass.to_s, view_name, @list_name)
|
15
|
+
@view_name = view_name
|
16
|
+
@options = options
|
17
|
+
|
18
|
+
@list_function = klass.lists(@list_name) if @list_name
|
19
|
+
@view_parameters = {}
|
20
|
+
[:group, :include_docs, :descending, :group_level, :limit].each do |key|
|
21
|
+
@view_parameters[key] = options[key] if options.include?(key)
|
22
|
+
end
|
23
|
+
@view_parameters.merge!(normalized_view_parameters)
|
24
|
+
end
|
25
|
+
|
26
|
+
def process_results(results)
|
27
|
+
results
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def normalize_view_parameters(params)
|
33
|
+
normalized_params = params.dup
|
34
|
+
hash = wrap_in_hash params
|
35
|
+
remove_nil_stale(replace_range_key(hash))
|
36
|
+
end
|
37
|
+
|
38
|
+
def remove_nil_stale(params)
|
39
|
+
params.reject{|name, value| name.to_s == 'stale' && value.nil?}
|
40
|
+
end
|
41
|
+
|
42
|
+
def wrap_in_hash(params)
|
43
|
+
if params.is_a?(Hash)
|
44
|
+
params
|
45
|
+
else
|
46
|
+
{:key => params}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def replace_range_key(params)
|
51
|
+
if((key = params[:key]).is_a?(Range))
|
52
|
+
params.delete :key
|
53
|
+
params[:startkey] = key.first
|
54
|
+
params[:endkey] = key.last
|
55
|
+
end
|
56
|
+
params
|
57
|
+
end
|
58
|
+
|
59
|
+
def assert_valid_view_parameters(params)
|
60
|
+
params.keys.each do |key|
|
61
|
+
raise ArgumentError.new("invalid view parameter: #{key}") unless valid_view_parameters.include?(key.to_s)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def valid_view_parameters
|
66
|
+
%w(key keys startkey startkey_docid endkey endkey_docid limit stale descending skip group group_level reduce include_docs inclusive_end)
|
67
|
+
end
|
68
|
+
|
69
|
+
def translate_to_design_doc_name(klass_name, view_name, list_name)
|
70
|
+
klass_name = klass_name.dup
|
71
|
+
klass_name.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
72
|
+
klass_name.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
73
|
+
klass_name.tr!("-", "_")
|
74
|
+
doc_name = klass_name.downcase
|
75
|
+
|
76
|
+
if CouchPotato::Config.split_design_documents_per_view
|
77
|
+
doc_name += "_view_#{view_name}" if view_name.present?
|
78
|
+
doc_name += "_list_#{list_name}" if list_name.present?
|
79
|
+
end
|
80
|
+
doc_name
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module CouchPotato
|
2
|
+
module View
|
3
|
+
# a view for custom map/reduce functions that still returns model instances
|
4
|
+
#
|
5
|
+
# example:
|
6
|
+
# view :my_custom_view, :map => "function(doc) { emit(doc._id, null); }", :include_docs => true, :type => :custom, :reduce => nil
|
7
|
+
class CustomViewSpec < BaseViewSpec
|
8
|
+
def map_function
|
9
|
+
options[:map]
|
10
|
+
end
|
11
|
+
|
12
|
+
def reduce_function
|
13
|
+
options[:reduce]
|
14
|
+
end
|
15
|
+
|
16
|
+
def view_parameters
|
17
|
+
{:include_docs => options[:include_docs] || false}.merge(super)
|
18
|
+
end
|
19
|
+
|
20
|
+
def process_results(results)
|
21
|
+
if count?
|
22
|
+
results['rows'].first.try(:[], 'value') || 0
|
23
|
+
else
|
24
|
+
results['rows'].map do |row|
|
25
|
+
if row['doc'].instance_of?(klass)
|
26
|
+
row['doc']
|
27
|
+
else
|
28
|
+
klass.json_create row['doc'] || row['value'].merge(:_id => row['id'] || row['key'])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def count?
|
37
|
+
view_parameters[:reduce]
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|