couch_potato 1.7.0 → 1.10.1
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.
- checksums.yaml +5 -5
- data/.github/workflows/ruby.yml +50 -0
- data/.gitignore +3 -0
- data/CHANGES.md +180 -130
- data/Gemfile +4 -0
- data/README.md +61 -85
- data/Rakefile +11 -10
- data/couch_potato-rspec.gemspec +2 -1
- data/couch_potato.gemspec +9 -7
- data/gemfiles/active_support_5_0 +6 -0
- data/gemfiles/active_support_5_1 +7 -0
- data/gemfiles/active_support_5_2 +6 -0
- data/gemfiles/active_support_6_0 +6 -0
- data/gemfiles/active_support_6_1 +6 -0
- data/gemfiles/active_support_7_0 +6 -0
- data/lib/couch_potato/database.rb +170 -71
- data/lib/couch_potato/persistence/dirty_attributes.rb +3 -21
- data/lib/couch_potato/persistence/magic_timestamps.rb +3 -3
- data/lib/couch_potato/persistence/properties.rb +15 -10
- data/lib/couch_potato/persistence/simple_property.rb +0 -4
- data/lib/couch_potato/persistence/type_caster.rb +11 -6
- data/lib/couch_potato/persistence.rb +0 -1
- data/lib/couch_potato/railtie.rb +6 -11
- data/lib/couch_potato/validation.rb +8 -0
- data/lib/couch_potato/version.rb +2 -2
- data/lib/couch_potato/view/base_view_spec.rb +8 -32
- data/lib/couch_potato/view/custom_views.rb +4 -3
- data/lib/couch_potato/view/flex_view_spec.rb +121 -0
- data/lib/couch_potato/view/view_parameters.rb +34 -0
- data/lib/couch_potato.rb +37 -16
- data/spec/callbacks_spec.rb +45 -19
- data/spec/conflict_handling_spec.rb +1 -2
- data/spec/property_spec.rb +12 -3
- data/spec/railtie_spec.rb +10 -0
- data/spec/spec_helper.rb +4 -3
- data/spec/unit/active_model_compliance_spec.rb +7 -3
- data/spec/unit/attributes_spec.rb +54 -1
- data/spec/unit/caching_spec.rb +105 -0
- data/spec/unit/couch_potato_spec.rb +70 -5
- data/spec/unit/create_spec.rb +5 -4
- data/spec/unit/database_spec.rb +239 -135
- data/spec/unit/dirty_attributes_spec.rb +5 -26
- data/spec/unit/flex_view_spec_spec.rb +17 -0
- data/spec/unit/model_view_spec_spec.rb +1 -1
- data/spec/unit/rspec_stub_db_spec.rb +31 -0
- data/spec/unit/validation_spec.rb +42 -2
- data/spec/unit/view_query_spec.rb +12 -7
- data/spec/views_spec.rb +214 -103
- data/vendor/pouchdb-collate/LICENSE +202 -0
- data/vendor/pouchdb-collate/pouchdb-collate.js +430 -0
- metadata +47 -36
- data/.ruby-version +0 -1
- data/.travis.yml +0 -21
- data/gemfiles/active_support_4_0 +0 -11
- data/gemfiles/active_support_4_1 +0 -11
- data/gemfiles/active_support_4_2 +0 -11
- data/lib/couch_potato/persistence/deep_dirty_attributes.rb +0 -180
- data/spec/unit/deep_dirty_attributes_spec.rb +0 -434
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'couch_potato/view/base_view_spec'
|
2
|
+
require 'couch_potato/view/flex_view_spec'
|
2
3
|
require 'couch_potato/view/model_view_spec'
|
3
4
|
require 'couch_potato/view/properties_view_spec'
|
4
5
|
require 'couch_potato/view/custom_view_spec'
|
5
6
|
require 'couch_potato/view/raw_view_spec'
|
6
|
-
|
7
|
+
require 'couch_potato/view/view_parameters'
|
7
8
|
|
8
9
|
module CouchPotato
|
9
10
|
module View
|
@@ -25,7 +26,7 @@ module CouchPotato
|
|
25
26
|
def execute_view(view_name, view_parameters) #:nodoc:
|
26
27
|
view_spec_class(views(view_name)[:type]).new(self, view_name, views(view_name), view_parameters)
|
27
28
|
end
|
28
|
-
|
29
|
+
|
29
30
|
# Declare a CouchDB view, for examples on how to use see the *ViewSpec classes in CouchPotato::View
|
30
31
|
def view(view_name, options)
|
31
32
|
view_name = view_name.to_s
|
@@ -42,7 +43,7 @@ module CouchPotato
|
|
42
43
|
CouchPotato::View.const_get("#{name}ViewSpec")
|
43
44
|
end
|
44
45
|
end
|
45
|
-
|
46
|
+
|
46
47
|
def _find_view(view) #:nodoc:
|
47
48
|
(@views && @views[view]) || (superclass._find_view(view) if superclass.respond_to?(:_find_view))
|
48
49
|
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CouchPotato
|
4
|
+
module View
|
5
|
+
# A flexible view spec.
|
6
|
+
# It allows to either just define a key and option conditions like
|
7
|
+
# the model view spec or custom map/reduce functions.
|
8
|
+
# In addition, it returns a result object that allows convenient access
|
9
|
+
# to either the raw result, the keys, values, ids or docs. The result object can
|
10
|
+
# be extended with custom module, too.
|
11
|
+
# Examples:
|
12
|
+
# class Thing
|
13
|
+
# module ResultsExt
|
14
|
+
# def average_time
|
15
|
+
# keys.sum / keys.size # can access other result methods
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
# property :time
|
19
|
+
# view :by_time, type: :flex, key: :time, extend_results: ResultsExt
|
20
|
+
# view :by_custom_time, type: :flex,
|
21
|
+
# reduce: '_sum'
|
22
|
+
# map: <<~JS
|
23
|
+
# function(doc) {
|
24
|
+
# emit(doc.time, 1);
|
25
|
+
# }
|
26
|
+
# JS
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# usage:
|
30
|
+
# irb> result = db.view Thing.by_time
|
31
|
+
# irb> result.raw # raw CouchDB results
|
32
|
+
# irb> result.ids # ids of rows
|
33
|
+
# irb> result.keys # keys emitted in map function
|
34
|
+
# irb> result.values # values emitted in map function
|
35
|
+
# irb> result.average_time # custom method from ResultsExt module
|
36
|
+
# irb> db.view(Thing.by_time(include_docs: true)).docs # documents
|
37
|
+
# irb> db.view(Thing.by_time(reduce: true)).reduce_value # value of first row, i.e. result of the reduce function (without grouping)
|
38
|
+
class FlexViewSpec
|
39
|
+
attr_reader :klass
|
40
|
+
|
41
|
+
class Results
|
42
|
+
attr_accessor :database # set by database
|
43
|
+
|
44
|
+
def initialize(raw_results)
|
45
|
+
@raw_results = raw_results
|
46
|
+
end
|
47
|
+
|
48
|
+
def raw
|
49
|
+
@raw_results
|
50
|
+
end
|
51
|
+
|
52
|
+
def ids
|
53
|
+
rows.map { |row| row['id'] }
|
54
|
+
end
|
55
|
+
|
56
|
+
def keys
|
57
|
+
rows.map { |row| row['key'] }
|
58
|
+
end
|
59
|
+
|
60
|
+
def values
|
61
|
+
rows.map { |row| row['value'] }
|
62
|
+
end
|
63
|
+
|
64
|
+
def reduce_value
|
65
|
+
rows.dig(0, 'value')
|
66
|
+
end
|
67
|
+
|
68
|
+
# returns a count from a CouchDB reduce. returns 0 when the result
|
69
|
+
# set is empty (which would result in `nil` when calling #reduce_value).
|
70
|
+
# you still have to pass reduce=true to the view call.
|
71
|
+
def reduce_count
|
72
|
+
reduce_value || 0
|
73
|
+
end
|
74
|
+
|
75
|
+
def docs
|
76
|
+
rows.map do |row|
|
77
|
+
doc = row['doc']
|
78
|
+
doc.database = database if doc.respond_to?(:database=)
|
79
|
+
doc
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def rows
|
84
|
+
@raw_results['rows']
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def initialize(klass, view_name, options, view_parameters)
|
89
|
+
@extend_results_module = options[:extend_results]
|
90
|
+
@klass = klass
|
91
|
+
@view_name = view_name
|
92
|
+
@options = options.except(:extend_results)
|
93
|
+
@view_parameters = view_parameters
|
94
|
+
end
|
95
|
+
|
96
|
+
delegate :view_name, :view_parameters, :design_document, :map_function,
|
97
|
+
:reduce_function, :list_name, :lib, :language, to: :view_spec_delegate
|
98
|
+
|
99
|
+
def process_results(results)
|
100
|
+
results = Results.new(results)
|
101
|
+
results.extend @extend_results_module if @extend_results_module
|
102
|
+
results
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def view_spec_delegate
|
108
|
+
unless @view_spec_delegate
|
109
|
+
view_spec_class = @options[:map] ? RawViewSpec : ModelViewSpec
|
110
|
+
@view_spec_delegate = view_spec_class.new(
|
111
|
+
@klass, @view_name, @options,
|
112
|
+
ViewParameters
|
113
|
+
.normalize_view_parameters(@view_parameters)
|
114
|
+
.reverse_merge(reduce: false, include_docs: false)
|
115
|
+
)
|
116
|
+
end
|
117
|
+
@view_spec_delegate
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module CouchPotato
|
2
|
+
module View
|
3
|
+
module ViewParameters
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def normalize_view_parameters(params)
|
7
|
+
hash = wrap_in_hash params
|
8
|
+
remove_nil_stale(replace_range_key(hash))
|
9
|
+
end
|
10
|
+
|
11
|
+
def remove_nil_stale(params)
|
12
|
+
params.reject{|name, value| name.to_s == 'stale' && value.nil?}
|
13
|
+
end
|
14
|
+
|
15
|
+
def wrap_in_hash(params)
|
16
|
+
if params.is_a?(Hash)
|
17
|
+
params
|
18
|
+
else
|
19
|
+
{:key => params}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def replace_range_key(params)
|
24
|
+
if((key = params[:key]).is_a?(Range))
|
25
|
+
params.delete :key
|
26
|
+
params[:startkey] = key.first
|
27
|
+
params[:endkey] = key.last
|
28
|
+
end
|
29
|
+
params
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/couch_potato.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'couchrest'
|
2
4
|
require 'json'
|
3
5
|
|
@@ -8,15 +10,30 @@ CouchRest.decode_json_objects = true
|
|
8
10
|
|
9
11
|
module CouchPotato
|
10
12
|
Config = Struct.new(:database_host, :database_name, :digest_view_names,
|
11
|
-
|
13
|
+
:split_design_documents_per_view, :default_language, :additional_databases).new
|
12
14
|
Config.split_design_documents_per_view = false
|
13
15
|
Config.digest_view_names = false
|
14
16
|
Config.default_language = :javascript
|
15
|
-
Config.database_host =
|
17
|
+
Config.database_host = 'http://127.0.0.1:5984'
|
18
|
+
Config.additional_databases = {}
|
16
19
|
|
17
20
|
class NotFound < StandardError; end
|
18
21
|
class Conflict < StandardError; end
|
19
22
|
|
23
|
+
def self.configure(config)
|
24
|
+
if config.is_a?(String)
|
25
|
+
Config.database_name = config
|
26
|
+
else
|
27
|
+
config = config.stringify_keys
|
28
|
+
Config.database_name = config['database']
|
29
|
+
Config.database_host = config['database_host'] if config['database_host']
|
30
|
+
Config.additional_databases = config['additional_databases'].stringify_keys if config['additional_databases']
|
31
|
+
Config.split_design_documents_per_view = config['split_design_documents_per_view'] if config['split_design_documents_per_view']
|
32
|
+
Config.digest_view_names = config['digest_view_names'] if config['digest_view_names']
|
33
|
+
Config.default_language = config['default_language'] if config['default_language']
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
20
37
|
# returns all the classes that include the CouchPotato::Persistence module
|
21
38
|
def self.models
|
22
39
|
@models ||= []
|
@@ -25,22 +42,27 @@ module CouchPotato
|
|
25
42
|
|
26
43
|
# Returns a database instance which you can then use to create objects and query views. You have to set the CouchPotato::Config.database_name before this works.
|
27
44
|
def self.database
|
28
|
-
|
45
|
+
Thread.current[:__couch_potato_database] ||= Database.new(couchrest_database)
|
29
46
|
end
|
30
47
|
|
31
48
|
# Returns the underlying CouchRest database object if you want low level access to your CouchDB. You have to set the CouchPotato::Config.database_name before this works.
|
32
49
|
def self.couchrest_database
|
33
|
-
|
50
|
+
Thread.current[:__couchrest_database] ||= CouchRest.database(full_url_to_database(CouchPotato::Config.database_name, CouchPotato::Config.database_host))
|
34
51
|
end
|
35
52
|
|
36
53
|
# Returns a specific database instance
|
37
54
|
def self.use(database_name)
|
38
|
-
|
39
|
-
|
40
|
-
|
55
|
+
resolved_database_name = resolve_database_name(database_name)
|
56
|
+
Thread.current[:__couch_potato_databases] ||= {}
|
57
|
+
Thread.current[:__couch_potato_databases][resolved_database_name] ||= Database.new(couchrest_database_for_name!(resolved_database_name), name: database_name)
|
41
58
|
end
|
42
59
|
|
43
|
-
#
|
60
|
+
# resolves a name to a database name/full url configured under additional databases
|
61
|
+
def self.resolve_database_name(database_name)
|
62
|
+
Config.additional_databases[database_name] || database_name
|
63
|
+
end
|
64
|
+
|
65
|
+
# Executes a block of code and yields a database with the given name.
|
44
66
|
#
|
45
67
|
# example:
|
46
68
|
# CouchPotato.with_database('couch_customer') do |couch|
|
@@ -48,25 +70,24 @@ module CouchPotato
|
|
48
70
|
# end
|
49
71
|
#
|
50
72
|
def self.with_database(database_name)
|
51
|
-
|
52
|
-
@@__databases["#{database_name}"] = Database.new(couchrest_database_for_name(database_name)) unless @@__databases["#{database_name}"]
|
53
|
-
yield(@@__databases["#{database_name}"])
|
73
|
+
yield use(database_name)
|
54
74
|
end
|
55
75
|
|
56
76
|
# Returns a CouchRest-Database for directly accessing that functionality.
|
57
77
|
def self.couchrest_database_for_name(database_name)
|
58
|
-
|
78
|
+
Thread.current[:__couchrest_databases] ||= {}
|
79
|
+
Thread.current[:__couchrest_databases][database_name] ||= CouchRest.database(full_url_to_database(database_name, CouchPotato::Config.database_host))
|
59
80
|
end
|
60
81
|
|
61
82
|
# Creates a CouchRest-Database for directly accessing that functionality.
|
62
83
|
def self.couchrest_database_for_name!(database_name)
|
63
|
-
|
84
|
+
Thread.current[:__couchrest_databases] ||= {}
|
85
|
+
Thread.current[:__couchrest_databases][database_name] ||= CouchRest.database!(full_url_to_database(database_name))
|
64
86
|
end
|
65
87
|
|
66
|
-
|
67
|
-
|
68
|
-
def self.full_url_to_database(database_name=CouchPotato::Config.database_name, database_host = CouchPotato::Config.database_host)
|
88
|
+
def self.full_url_to_database(database_name = CouchPotato::Config.database_name, database_host = CouchPotato::Config.database_host)
|
69
89
|
raise('No Database configured. Set CouchPotato::Config.database_name') unless database_name
|
90
|
+
|
70
91
|
if database_name.match(%r{https?://})
|
71
92
|
database_name
|
72
93
|
else
|
data/spec/callbacks_spec.rb
CHANGED
@@ -382,13 +382,13 @@ describe "validation callbacks and filter halt" do
|
|
382
382
|
|
383
383
|
property :name
|
384
384
|
before_validation :check_name
|
385
|
-
before_validation_on_update :
|
385
|
+
before_validation_on_update :abort_callback
|
386
386
|
|
387
387
|
def check_name
|
388
388
|
errors.add(:name, 'should be Paul') unless name == "Paul"
|
389
389
|
end
|
390
390
|
|
391
|
-
def
|
391
|
+
def abort_callback
|
392
392
|
false
|
393
393
|
end
|
394
394
|
end
|
@@ -398,14 +398,14 @@ describe "validation callbacks and filter halt" do
|
|
398
398
|
|
399
399
|
property :name
|
400
400
|
before_validation :check_name
|
401
|
-
before_validation_on_save :
|
402
|
-
before_validation_on_create :
|
401
|
+
before_validation_on_save :abort_callback
|
402
|
+
before_validation_on_create :abort_callback
|
403
403
|
|
404
404
|
def check_name
|
405
405
|
errors.add(:name, 'should be Paul') unless name == "Paul"
|
406
406
|
end
|
407
407
|
|
408
|
-
def
|
408
|
+
def abort_callback
|
409
409
|
false
|
410
410
|
end
|
411
411
|
end
|
@@ -414,9 +414,9 @@ describe "validation callbacks and filter halt" do
|
|
414
414
|
include CouchPotato::Persistence
|
415
415
|
|
416
416
|
property :name
|
417
|
-
before_update :
|
417
|
+
before_update :abort_callback
|
418
418
|
|
419
|
-
def
|
419
|
+
def abort_callback
|
420
420
|
false
|
421
421
|
end
|
422
422
|
end
|
@@ -425,10 +425,10 @@ describe "validation callbacks and filter halt" do
|
|
425
425
|
include CouchPotato::Persistence
|
426
426
|
|
427
427
|
property :name
|
428
|
-
before_save :
|
429
|
-
before_create :
|
428
|
+
before_save :abort_callback
|
429
|
+
before_create :abort_callback
|
430
430
|
|
431
|
-
def
|
431
|
+
def abort_callback
|
432
432
|
false
|
433
433
|
end
|
434
434
|
end
|
@@ -450,16 +450,42 @@ describe "validation callbacks and filter halt" do
|
|
450
450
|
expect(@db.save_document(@user)).to eq(false)
|
451
451
|
end
|
452
452
|
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
453
|
+
if ActiveModel.version.segments.first < 5
|
454
|
+
it "should return false on saving a document when a before update filter returned false" do
|
455
|
+
@user = FilterSaveUpdateUser.new(:name => "Paul")
|
456
|
+
expect(@db.save_document(@user)).to eq(true)
|
457
|
+
@user.name = 'Bert'
|
458
|
+
expect(@db.save_document(@user)).to eq(false)
|
459
|
+
end
|
459
460
|
|
460
|
-
|
461
|
-
|
462
|
-
|
461
|
+
it "should return false on saving a document when a before save or before create filter returned false" do
|
462
|
+
@user = FilterSaveCreateUser.new(:name => "Bert")
|
463
|
+
expect(@db.save_document(@user)).to eq(false)
|
464
|
+
end
|
465
|
+
else
|
466
|
+
class FilterSaveCreateUser5 < FilterSaveCreateUser
|
467
|
+
def abort_callback
|
468
|
+
throw :abort
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
class FilterSaveUpdateUser5 < FilterSaveUpdateUser
|
473
|
+
def abort_callback
|
474
|
+
throw :abort
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
it "returns false on saving a document when a before update filter throws :abort" do
|
479
|
+
@user = FilterSaveUpdateUser5.new(:name => "Paul")
|
480
|
+
expect(@db.save_document(@user)).to eq(true)
|
481
|
+
@user.name = 'Bert'
|
482
|
+
expect(@db.save_document(@user)).to eq(false)
|
483
|
+
end
|
484
|
+
|
485
|
+
it "returns false on saving a document when a before save or before create filter throws :abort" do
|
486
|
+
@user = FilterSaveCreateUser5.new(:name => "Bert")
|
487
|
+
expect(@db.save_document(@user)).to eq(false)
|
488
|
+
end
|
463
489
|
end
|
464
490
|
|
465
491
|
end
|
@@ -14,12 +14,11 @@ describe 'conflict handling' do
|
|
14
14
|
|
15
15
|
db.couchrest_database.save_doc measurement.reload._document.merge('value' => 2)
|
16
16
|
|
17
|
-
measurement.is_dirty
|
18
17
|
db.save measurement do |m|
|
19
18
|
m.value += 1
|
20
19
|
end
|
21
20
|
|
22
|
-
expect(measurement.
|
21
|
+
expect(measurement.value).to eql(3)
|
23
22
|
end
|
24
23
|
|
25
24
|
it 'raises an error after 5 tries' do
|
data/spec/property_spec.rb
CHANGED
@@ -93,10 +93,10 @@ describe 'properties' do
|
|
93
93
|
|
94
94
|
it "should persist a big decimal" do
|
95
95
|
require 'bigdecimal'
|
96
|
-
c = BigDecimalContainer.new :number => BigDecimal
|
96
|
+
c = BigDecimalContainer.new :number => BigDecimal( '42.42' )
|
97
97
|
CouchPotato.database.save_document! c
|
98
98
|
c = CouchPotato.database.load_document c.id
|
99
|
-
expect(c.number).to eq(BigDecimal
|
99
|
+
expect(c.number).to eq(BigDecimal( '42.42' ))
|
100
100
|
end
|
101
101
|
|
102
102
|
it "should persist a hash" do
|
@@ -114,12 +114,21 @@ describe 'properties' do
|
|
114
114
|
end
|
115
115
|
|
116
116
|
it "should persist subclasses of the specified type" do
|
117
|
-
w = Watch.new(:custom_address => [Address2.new])
|
117
|
+
w = Watch.new(:custom_address => [Address2.new(id: 'a1', city: 'Berlin')])
|
118
118
|
CouchPotato.database.save_document! w
|
119
119
|
w = CouchPotato.database.load_document w.id
|
120
|
+
|
120
121
|
expect(w.custom_address[0]).to be_an_instance_of Address2
|
121
122
|
end
|
122
123
|
|
124
|
+
it 'initializes an typed array property from an array of hashes' do
|
125
|
+
w = Watch.new(custom_address: [{id: 'a1', city: 'Berlin'}])
|
126
|
+
|
127
|
+
expect(w.custom_address.map(&:class)).to eq([Address])
|
128
|
+
expect(w.custom_address.map(&:id)).to eq(['a1'])
|
129
|
+
expect(w.custom_address.map(&:city)).to eq(['Berlin'])
|
130
|
+
end
|
131
|
+
|
123
132
|
def it_should_persist value
|
124
133
|
c = Comment.new :title => value
|
125
134
|
CouchPotato.database.save_document! c
|
data/spec/railtie_spec.rb
CHANGED
@@ -83,6 +83,16 @@ describe "railtie" do
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
+
context 'yaml file contains additional_databases' do
|
87
|
+
it 'assigns additional_databases to config' do
|
88
|
+
allow(File).to receive_messages(:read => "test:\n database: test\n additional_databases:\n db2: test2")
|
89
|
+
|
90
|
+
expect(CouchPotato::Config).to receive(:additional_databases=).with({'db2' => 'test2'})
|
91
|
+
|
92
|
+
CouchPotato.rails_init
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
86
96
|
it "should process the yml file with erb" do
|
87
97
|
allow(File).to receive_messages(:read => "test: \n database: <%= 'db' %>")
|
88
98
|
|
data/spec/spec_helper.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rubygems'
|
2
4
|
require 'rspec'
|
3
5
|
require 'time'
|
4
6
|
require 'active_support'
|
5
7
|
require 'timecop'
|
6
8
|
|
7
|
-
|
9
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
|
8
10
|
|
9
11
|
require 'couch_potato'
|
10
12
|
|
@@ -13,7 +15,7 @@ CouchPotato::Config.database_name = ENV['DATABASE'] || 'couch_potato_test'
|
|
13
15
|
# silence deprecation warnings from ActiveModel as the Spec uses Errors#on
|
14
16
|
begin
|
15
17
|
ActiveSupport::Deprecation.silenced = true
|
16
|
-
rescue
|
18
|
+
rescue StandardError
|
17
19
|
# ignore errors, ActiveSupport is probably not installed
|
18
20
|
end
|
19
21
|
|
@@ -64,5 +66,4 @@ RSpec::Matchers.define :eql_ignoring_indentation do |expected|
|
|
64
66
|
def strip_indentation(string)
|
65
67
|
string.gsub(/^\s+/m, '')
|
66
68
|
end
|
67
|
-
|
68
69
|
end
|
@@ -12,8 +12,12 @@ begin
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
def assert_equal(one, other)
|
16
|
-
expect(one).to
|
15
|
+
def assert_equal(one, other, _message = nil)
|
16
|
+
expect(one).to eq(other)
|
17
|
+
end
|
18
|
+
|
19
|
+
def assert_respond_to(receiver, method)
|
20
|
+
expect(receiver).to respond_to(method)
|
17
21
|
end
|
18
22
|
|
19
23
|
class ActiveComment
|
@@ -62,7 +66,7 @@ begin
|
|
62
66
|
describe "#errors" do
|
63
67
|
it "should return a single error as array" do
|
64
68
|
@model.valid?
|
65
|
-
expect(@model.errors[:name]).to
|
69
|
+
expect(@model.errors[:name]).to eq(["can't be blank"])
|
66
70
|
end
|
67
71
|
|
68
72
|
it "should return multiple errors as array" do
|
@@ -10,7 +10,8 @@ class Plant
|
|
10
10
|
include CouchPotato::Persistence
|
11
11
|
property :leaf_count
|
12
12
|
property :typed_leaf_count, type: Fixnum
|
13
|
-
property :
|
13
|
+
property :integer_something, type: Integer
|
14
|
+
property :typed_leaf_size, type: Float
|
14
15
|
property :branch, type: Branch
|
15
16
|
end
|
16
17
|
|
@@ -40,6 +41,7 @@ describe 'attributes' do
|
|
40
41
|
plant = Plant.new(leaf_count: 1)
|
41
42
|
|
42
43
|
expect(plant.attributes).to eq('leaf_count' => 1, 'created_at' => nil,
|
44
|
+
'integer_something' => nil,
|
43
45
|
'updated_at' => nil, 'typed_leaf_count' => nil,
|
44
46
|
'typed_leaf_size' => nil, 'branch' => nil)
|
45
47
|
end
|
@@ -109,6 +111,57 @@ describe 'attributes' do
|
|
109
111
|
end
|
110
112
|
end
|
111
113
|
|
114
|
+
describe 'integer' do
|
115
|
+
it 'rounds a float to a fixnum' do
|
116
|
+
@plant.integer_something = 4.5
|
117
|
+
|
118
|
+
expect(@plant.integer_something).to eq(5)
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'converts a string into a fixnum' do
|
122
|
+
@plant.integer_something = '4'
|
123
|
+
|
124
|
+
expect(@plant.integer_something).to eq(4)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'converts a string into a negative fixnum' do
|
128
|
+
@plant.integer_something = '-4'
|
129
|
+
|
130
|
+
expect(@plant.integer_something).to eq(-4)
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'leaves a fixnum as is' do
|
134
|
+
@plant.integer_something = 4
|
135
|
+
|
136
|
+
expect(@plant.integer_something).to eq(4)
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'leaves nil as is' do
|
140
|
+
@plant.integer_something = nil
|
141
|
+
|
142
|
+
expect(@plant.integer_something).to be_nil
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'sets the attributes to zero if a string given' do
|
146
|
+
@plant.integer_something = 'x'
|
147
|
+
|
148
|
+
expect(@plant.integer_something).to eq(0)
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'parses numbers out of a string' do
|
152
|
+
@plant.integer_something = 'x123'
|
153
|
+
|
154
|
+
expect(@plant.integer_something).to eq(123)
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'sets the attributes to nil if given a blank string' do
|
158
|
+
@plant.integer_something = ''
|
159
|
+
|
160
|
+
expect(@plant.integer_something).to be_nil
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
|
112
165
|
describe 'fixnum' do
|
113
166
|
it 'rounds a float to a fixnum' do
|
114
167
|
@plant.typed_leaf_count = 4.5
|