couchrest_model 2.0.4 → 2.1.0.beta1
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 +4 -4
- data/.travis.yml +6 -2
- data/README.md +12 -3
- data/VERSION +1 -1
- data/benchmarks/Gemfile +7 -0
- data/benchmarks/connections.rb +69 -0
- data/couchrest_model.gemspec +11 -13
- data/history.md +6 -0
- data/lib/couchrest/model/design.rb +0 -2
- data/lib/couchrest/model/designs/view.rb +36 -16
- data/lib/couchrest/model/document_queries.rb +5 -9
- data/lib/couchrest/model/errors.rb +8 -0
- data/lib/couchrest/model/support/couchrest_database.rb +12 -4
- data/lib/couchrest/model/validations.rb +1 -1
- data/lib/couchrest/model/validations/uniqueness.rb +11 -1
- data/spec/fixtures/models/course.rb +1 -1
- data/spec/spec_helper.rb +2 -2
- data/spec/unit/assocations_spec.rb +1 -1
- data/spec/unit/attachment_spec.rb +1 -1
- data/spec/unit/base_spec.rb +5 -5
- data/spec/unit/casted_spec.rb +2 -2
- data/spec/unit/connection_spec.rb +3 -3
- data/spec/unit/design_spec.rb +2 -2
- data/spec/unit/designs/design_mapper_spec.rb +1 -1
- data/spec/unit/designs/migrations_spec.rb +1 -1
- data/spec/unit/designs/view_spec.rb +118 -43
- data/spec/unit/designs_spec.rb +10 -13
- data/spec/unit/embeddable_spec.rb +2 -4
- data/spec/unit/persistence_spec.rb +13 -5
- data/spec/unit/property_protection_spec.rb +5 -5
- data/spec/unit/property_spec.rb +9 -9
- data/spec/unit/proxyable_spec.rb +15 -15
- data/spec/unit/subclass_spec.rb +1 -1
- data/spec/unit/utils/migrate_spec.rb +3 -3
- data/spec/unit/validations_spec.rb +7 -7
- metadata +60 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57c0015876d459e0bee7cfb9e3f59a2aa5231d1d
|
4
|
+
data.tar.gz: 7c0e6f7444fa9e73fc041946c5736f94eb42b765
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 306a335f39a5530bd4273731affe1f1c238b0e487177d3340b8c6e9cefa885ec2e2048182cd008b3a3ab12ca31d487110f8e0bca036d28639b8d1b74c8872238
|
7
|
+
data.tar.gz: 9d09641f25b138dbb3c56cfbbe2663947d6ed04135a64d5d4157b8f94d068881989ac79f0f19d7e0c1af64cee4d42aedc9534becdc26c97551b04c8193ef0a5e
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -7,7 +7,7 @@ CouchRest Model helps you define models that are stored as documents in your Cou
|
|
7
7
|
It supports useful features such as setting properties with typecasting, callbacks, validations, associations, and helps
|
8
8
|
with creating CouchDB views to access your data.
|
9
9
|
|
10
|
-
CouchRest Model uses ActiveModel for a lot of the magic, so if you're using Rails, you'll need at least version 3.0.
|
10
|
+
CouchRest Model uses ActiveModel for a lot of the magic, so if you're using Rails, you'll need at least version 3.0. Releases since 2.0.0 are Rails 4.0 compatible, and we recommend Ruby 2.0+.
|
11
11
|
|
12
12
|
## Documentation
|
13
13
|
|
@@ -60,9 +60,9 @@ The library will try to detect a configuration file at `config/couchdb.yml` from
|
|
60
60
|
username: test
|
61
61
|
password: user
|
62
62
|
|
63
|
-
Note that the name of the database is either just the prefix and suffix combined or the prefix plus any text you
|
63
|
+
Note that the name of the database is either just the prefix and suffix combined or the prefix plus any text you specify using `use_database` method in your models with the suffix on the end.
|
64
64
|
|
65
|
-
The example config above for example would use a database called "project_test".
|
65
|
+
The example config above for example would use a database called "project_test". Here's an example using the `use_database` call:
|
66
66
|
|
67
67
|
```ruby
|
68
68
|
class Project < CouchRest::Model::Base
|
@@ -140,6 +140,15 @@ end
|
|
140
140
|
@cat.update_attributes(:name => 'Felix', :random_text => 'feline')
|
141
141
|
@cat.new? # false
|
142
142
|
@cat.random_text # Raises error!
|
143
|
+
|
144
|
+
# Fetching by views, loading all results into memory
|
145
|
+
cats = Cat.by_name.all
|
146
|
+
cats.first.name # "Felix"
|
147
|
+
|
148
|
+
# Streaming views, for efficient memory usage
|
149
|
+
Cat.by_name.all do |cat|
|
150
|
+
puts cat.name
|
151
|
+
end
|
143
152
|
```
|
144
153
|
|
145
154
|
## Development
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.0.
|
1
|
+
2.1.0.beta1
|
data/benchmarks/Gemfile
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
#
|
2
|
+
# Simple Benchmarking Script.
|
3
|
+
#
|
4
|
+
# Meant to test performance for different types on connections under a typical
|
5
|
+
# scenario of requesting multiple objects from the database in series.
|
6
|
+
#
|
7
|
+
# To run, use `bundle install` then:
|
8
|
+
#
|
9
|
+
# bundle exec ruby connections.rb
|
10
|
+
#
|
11
|
+
|
12
|
+
require 'rubygems'
|
13
|
+
require 'bundler/setup'
|
14
|
+
|
15
|
+
require 'benchmark'
|
16
|
+
require 'couchrest_model'
|
17
|
+
require 'faker'
|
18
|
+
|
19
|
+
class SampleModel < CouchRest::Model::Base
|
20
|
+
use_database "benchmark"
|
21
|
+
|
22
|
+
property :name, String
|
23
|
+
property :date, Date
|
24
|
+
|
25
|
+
timestamps!
|
26
|
+
|
27
|
+
design do
|
28
|
+
view :by_name
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
Benchmark.bm do |x|
|
34
|
+
x.report("Create: ") do
|
35
|
+
100.times do |i|
|
36
|
+
m = SampleModel.new(
|
37
|
+
name: Faker::Name.name,
|
38
|
+
date: Faker::Date.between(1.year.ago, Date.today)
|
39
|
+
)
|
40
|
+
m.save!
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Make sure the view is fresh
|
45
|
+
SampleModel.by_name.limit(1).rows
|
46
|
+
|
47
|
+
x.report("Fetch inc/docs:") do
|
48
|
+
SampleModel.by_name.all.each do |doc|
|
49
|
+
doc.to_json
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
x.report("Fetch: ") do
|
54
|
+
SampleModel.by_name.rows.each do |row|
|
55
|
+
row.doc.to_json # Causes each doc to be fetched
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if CouchRest::Model::VERSION >= '2.1.0'
|
60
|
+
x.report("Fetch w/block: ") do
|
61
|
+
SampleModel.by_name.rows do |row|
|
62
|
+
row.doc.to_json # Causes each doc to be fetched
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
SampleModel.database.delete!
|
69
|
+
|
data/couchrest_model.gemspec
CHANGED
@@ -14,24 +14,22 @@ Gem::Specification.new do |s|
|
|
14
14
|
"THANKS.md"
|
15
15
|
]
|
16
16
|
s.homepage = %q{http://github.com/couchrest/couchrest_model}
|
17
|
-
s.rubygems_version = %q{1.3.7}
|
18
|
-
s.summary = %q{Extends the CouchRest Document for advanced modelling.}
|
17
|
+
#s.rubygems_version = %q{1.3.7}
|
18
|
+
s.summary = %q{Extends the CouchRest Document class for advanced modelling.}
|
19
19
|
|
20
20
|
s.files = `git ls-files`.split("\n")
|
21
21
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
22
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
23
|
s.require_paths = ["lib"]
|
24
24
|
|
25
|
-
s.add_dependency(
|
26
|
-
s.add_dependency(
|
27
|
-
s.add_dependency(
|
28
|
-
s.
|
29
|
-
s.add_development_dependency(
|
30
|
-
s.add_development_dependency(%q<json>, ["~> 1.5.1"])
|
31
|
-
s.add_development_dependency(%q<rack-test>, ">= 0.5.7")
|
25
|
+
s.add_dependency("couchrest", "2.0.0.rc3")
|
26
|
+
s.add_dependency("activemodel", "~> 4.0")
|
27
|
+
s.add_dependency("tzinfo", ">= 0.3.22")
|
28
|
+
s.add_development_dependency("rspec", "~> 2.14.1")
|
29
|
+
s.add_development_dependency("rack-test", ">= 0.5.7")
|
32
30
|
s.add_development_dependency("rake", ">= 0.8.0")
|
33
|
-
|
34
|
-
|
35
|
-
s.add_development_dependency("kaminari", "
|
36
|
-
|
31
|
+
s.add_development_dependency("test-unit")
|
32
|
+
s.add_development_dependency("minitest", "> 4.1") #, "< 5.0") # For Kaminari and activesupport, pending removal
|
33
|
+
s.add_development_dependency("kaminari", ">= 0.14.1", "< 0.16.0")
|
34
|
+
s.add_development_dependency("mime-types", "< 3.0") # Mime-types > 3.0 don't bundle properly on JRuby
|
37
35
|
end
|
data/history.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# CouchRest Model Change History
|
2
2
|
|
3
|
+
## 2.1.0.beta1 - 2016-01-13
|
4
|
+
|
5
|
+
* Upgrading to CouchRest 2.0.0 series (@samlown)
|
6
|
+
* Support for streaming in View objects (@samlown)
|
7
|
+
* Support for ActiveModel >= 4.1 (@samlown)
|
8
|
+
|
3
9
|
## 2.0.4 - 2015-06-26
|
4
10
|
|
5
11
|
* Casting Array properties using anything that inherits from Hash. (@samlown)
|
@@ -58,10 +58,16 @@ module CouchRest
|
|
58
58
|
# are no results.
|
59
59
|
def rows
|
60
60
|
return @rows if @rows
|
61
|
-
if
|
62
|
-
|
63
|
-
|
64
|
-
|
61
|
+
if block_given?
|
62
|
+
execute do |row|
|
63
|
+
yield ViewRow.new(row, model, use_database)
|
64
|
+
end
|
65
|
+
else
|
66
|
+
if execute && result['rows']
|
67
|
+
@rows ||= result['rows'].map{|v| ViewRow.new(v, model, use_database)}
|
68
|
+
else
|
69
|
+
[ ]
|
70
|
+
end
|
65
71
|
end
|
66
72
|
end
|
67
73
|
|
@@ -69,16 +75,22 @@ module CouchRest
|
|
69
75
|
# not already been prepared for including documents in the query,
|
70
76
|
# it will be added automatically and reset any previously cached
|
71
77
|
# results.
|
72
|
-
def all
|
78
|
+
def all(&block)
|
73
79
|
include_docs!
|
74
|
-
docs
|
80
|
+
docs(&block)
|
75
81
|
end
|
76
82
|
|
77
83
|
# Provide all the documents from the view. If the view has not been
|
78
84
|
# prepared with the +include_docs+ option, each document will be
|
79
85
|
# loaded individually.
|
80
86
|
def docs
|
81
|
-
|
87
|
+
if block_given?
|
88
|
+
rows do |row|
|
89
|
+
yield row.doc
|
90
|
+
end
|
91
|
+
else
|
92
|
+
@docs ||= rows.map{|r| r.doc}
|
93
|
+
end
|
82
94
|
end
|
83
95
|
|
84
96
|
# If another request has been made on the view, this will return
|
@@ -413,16 +425,16 @@ module CouchRest
|
|
413
425
|
query[:database] || model.database
|
414
426
|
end
|
415
427
|
|
416
|
-
def execute
|
428
|
+
def execute(&block)
|
417
429
|
return self.result if result
|
418
|
-
raise
|
430
|
+
raise CouchRest::Model::DatabaseNotDefined if use_database.nil?
|
419
431
|
|
420
432
|
# Remove the reduce value if its not needed to prevent CouchDB errors
|
421
433
|
query.delete(:reduce) unless can_reduce?
|
422
434
|
|
423
435
|
design_doc.sync(use_database)
|
424
436
|
|
425
|
-
self.result = design_doc.view_on(use_database, name, query)
|
437
|
+
self.result = design_doc.view_on(use_database, name, query, &block)
|
426
438
|
end
|
427
439
|
|
428
440
|
# Class Methods
|
@@ -535,9 +547,10 @@ module CouchRest
|
|
535
547
|
# A special wrapper class that provides easy access to the key
|
536
548
|
# fields in a result row.
|
537
549
|
class ViewRow < Hash
|
538
|
-
attr_reader :model
|
539
|
-
def initialize(hash, model)
|
540
|
-
@model
|
550
|
+
attr_reader :model, :db
|
551
|
+
def initialize(hash, model, db = nil)
|
552
|
+
@model = model
|
553
|
+
@db = db || model.database
|
541
554
|
replace(hash)
|
542
555
|
end
|
543
556
|
def id
|
@@ -555,9 +568,16 @@ module CouchRest
|
|
555
568
|
# Send a request for the linked document either using the "id" field's
|
556
569
|
# value, or the ["value"]["_id"] used for linked documents.
|
557
570
|
def doc
|
558
|
-
|
559
|
-
|
560
|
-
|
571
|
+
@doc ||= begin
|
572
|
+
if self['doc']
|
573
|
+
obj = model.build_from_database(self['doc'])
|
574
|
+
obj.database ||= db
|
575
|
+
obj
|
576
|
+
else
|
577
|
+
doc_id = (value.is_a?(Hash) && value['_id']) ? value['_id'] : self.id
|
578
|
+
doc_id ? model.get(doc_id, db) : nil
|
579
|
+
end
|
580
|
+
end
|
561
581
|
end
|
562
582
|
end
|
563
583
|
|
@@ -33,11 +33,9 @@ module CouchRest
|
|
33
33
|
# id<String, Integer>:: Document ID
|
34
34
|
# db<Database>:: optional option to pass a custom database to use
|
35
35
|
def get(id, db = database)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
nil
|
40
|
-
end
|
36
|
+
get!(id, db)
|
37
|
+
rescue CouchRest::Model::DocumentNotFound
|
38
|
+
nil
|
41
39
|
end
|
42
40
|
alias :find :get
|
43
41
|
|
@@ -54,11 +52,9 @@ module CouchRest
|
|
54
52
|
# db<Database>:: optional option to pass a custom database to use
|
55
53
|
def get!(id, db = database)
|
56
54
|
raise CouchRest::Model::DocumentNotFound if id.blank?
|
57
|
-
|
58
|
-
doc = db.get
|
55
|
+
raise CouchRest::Model::DatabaseNotDefined if db.nil?
|
56
|
+
doc = db.get(id) or raise CouchRest::Model::DocumentNotFound
|
59
57
|
build_from_database(doc)
|
60
|
-
rescue RestClient::ResourceNotFound
|
61
|
-
raise CouchRest::Model::DocumentNotFound
|
62
58
|
end
|
63
59
|
alias :find! :get!
|
64
60
|
|
@@ -21,5 +21,13 @@ module CouchRest
|
|
21
21
|
end
|
22
22
|
|
23
23
|
class DocumentNotFound < Errors::CouchRestModelError; end
|
24
|
+
|
25
|
+
class DatabaseNotDefined < Errors::CouchRestModelError
|
26
|
+
def initialize(msg = nil)
|
27
|
+
msg ||= "Database must be defined in model or view!"
|
28
|
+
super(msg)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
24
32
|
end
|
25
33
|
end
|
@@ -3,11 +3,19 @@
|
|
3
3
|
# also emptied. Given that this is a rare event, and the consequences are not
|
4
4
|
# very severe, we just completely empty the cache.
|
5
5
|
#
|
6
|
-
CouchRest::
|
6
|
+
module CouchRest::Model
|
7
|
+
module Support
|
8
|
+
module Database
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
-
|
10
|
+
def delete!
|
11
|
+
Thread.current[:couchrest_design_cache] = { }
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
11
16
|
end
|
17
|
+
end
|
12
18
|
|
19
|
+
class CouchRest::Database
|
20
|
+
include(CouchRest::Model::Support::Database)
|
13
21
|
end
|
@@ -55,7 +55,7 @@ module CouchRest
|
|
55
55
|
# Asside from the standard options, you can specify the name of the view you'd like
|
56
56
|
# to use for the search inside the +:view+ option. The following example would search
|
57
57
|
# for the code in side the +all+ view, useful for when +unique_id+ is used and you'd
|
58
|
-
# like to check before receiving a
|
58
|
+
# like to check before receiving a CouchRest::Conflict error:
|
59
59
|
#
|
60
60
|
# validates_uniqueness_of :code, :view => 'all'
|
61
61
|
#
|
@@ -7,9 +7,16 @@ module CouchRest
|
|
7
7
|
# Validates if a field is unique
|
8
8
|
class UniquenessValidator < ActiveModel::EachValidator
|
9
9
|
|
10
|
+
SETUP_DEPRECATED = ActiveModel.respond_to?(:version) && ActiveModel.version >= Gem::Version.new('4.1')
|
11
|
+
|
12
|
+
def initialize(options = {})
|
13
|
+
super
|
14
|
+
setup_uniqueness_validation(options[:class]) if options[:class]
|
15
|
+
end
|
16
|
+
|
10
17
|
# Ensure we have a class available so we can check for a usable view
|
11
18
|
# or add one if necessary.
|
12
|
-
def
|
19
|
+
def setup_uniqueness_validation(model)
|
13
20
|
@model = model
|
14
21
|
if options[:view].blank?
|
15
22
|
attributes.each do |attribute|
|
@@ -24,6 +31,9 @@ module CouchRest
|
|
24
31
|
end
|
25
32
|
end
|
26
33
|
|
34
|
+
# Provide backwards compatibility for Rails < 4.1, which expects `#setup` to be defined.
|
35
|
+
alias_method :setup, :setup_uniqueness_validation unless SETUP_DEPRECATED
|
36
|
+
|
27
37
|
def validate_each(document, attribute, value)
|
28
38
|
opts = merge_view_options(attribute)
|
29
39
|
|
data/spec/spec_helper.rb
CHANGED
@@ -18,7 +18,7 @@ unless defined?(FIXTURE_PATH)
|
|
18
18
|
COUCHHOST = "http://127.0.0.1:5984"
|
19
19
|
TESTDB = 'couchrest-model-test'
|
20
20
|
TEST_SERVER = CouchRest.new COUCHHOST
|
21
|
-
TEST_SERVER.default_database = TESTDB
|
21
|
+
# TEST_SERVER.default_database = TESTDB
|
22
22
|
DB = TEST_SERVER.database(TESTDB)
|
23
23
|
end
|
24
24
|
|
@@ -38,7 +38,7 @@ end
|
|
38
38
|
Dir[ File.join(MODEL_PATH, "*.rb") ].sort.each { |file| require File.basename(file) }
|
39
39
|
|
40
40
|
class Basic < CouchRest::Model::Base
|
41
|
-
use_database
|
41
|
+
use_database DB
|
42
42
|
end
|
43
43
|
|
44
44
|
def reset_test_db!
|
@@ -25,7 +25,7 @@ describe "Assocations" do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should generate a proxy string if proxied" do
|
28
|
-
SaleInvoice.stub
|
28
|
+
SaleInvoice.stub(:proxy_owner_method).twice.and_return('company')
|
29
29
|
o = SaleInvoice.merge_assoc_opts(:cat)
|
30
30
|
o[:proxy].should eql('self.company.cats')
|
31
31
|
end
|