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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dc12bf9934bec928c3317599950ad2ac7b57e623
4
- data.tar.gz: 4244221435ea4d8dbd33a6c184ed97926ba5cf14
3
+ metadata.gz: 57c0015876d459e0bee7cfb9e3f59a2aa5231d1d
4
+ data.tar.gz: 7c0e6f7444fa9e73fc041946c5736f94eb42b765
5
5
  SHA512:
6
- metadata.gz: 337c15afdd8264dfd16341d50ac85a25f8651946f0b1994135e02ac118f63dbde6c7688c4a21e44e21eb639d85aa0f892d979b5465f3d9c516fd9141a9433756
7
- data.tar.gz: 9200d9be82615a00e475f05947ccbcef682ab5867a23810368146db85064a63ac46f8f6453efd661a64c16f805376060d65dddcc58cae74ec7892637aeebcfe8
6
+ metadata.gz: 306a335f39a5530bd4273731affe1f1c238b0e487177d3340b8c6e9cefa885ec2e2048182cd008b3a3ab12ca31d487110f8e0bca036d28639b8d1b74c8872238
7
+ data.tar.gz: 9d09641f25b138dbb3c56cfbbe2663947d6ed04135a64d5d4157b8f94d068881989ac79f0f19d7e0c1af64cee4d42aedc9534becdc26c97551b04c8193ef0a5e
@@ -1,8 +1,12 @@
1
1
  rvm:
2
+ - 2.3.0
3
+ - 2.2.2
4
+ - 2.1.5
2
5
  - 2.0.0
3
- - 1.9.3
4
- - jruby
6
+ - jruby-19mode
5
7
  services: couchdb
6
8
  matrix:
7
9
  allow_failures:
8
10
  - rvm: jruby
11
+ before_install:
12
+ - gem install bundler
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. The latest release (since 2.0.0) is Rails 4.0 compatible, and we recommend Ruby 2.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 specifify using `use_database` method in your models with the suffix on the end.
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". Heres an example using the `use_database` call:
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.4
1
+ 2.1.0.beta1
@@ -0,0 +1,7 @@
1
+
2
+ source 'https://rubygems.org'
3
+
4
+ #gem 'couchrest_model', '2.0.4'
5
+ gem 'couchrest_model', path: '../'
6
+ gem 'faker'
7
+
@@ -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
+
@@ -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(%q<couchrest>, "~> 1.2.1")
26
- s.add_dependency(%q<mime-types>, ">= 1.16")
27
- s.add_dependency(%q<activemodel>, ">= 4.0", ">= 3.0")
28
- s.add_dependency(%q<tzinfo>, ">= 0.3.22")
29
- s.add_development_dependency(%q<rspec>, "~> 2.6.0")
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
- #s.add_development_dependency("debugger", "~> 1.2.0") # TODO put in Gemfile
34
- #s.add_development_dependency(%q<oj>, "~> 1.3.4") # TODO put in Gemfile (fails in JRuby)
35
- s.add_development_dependency("kaminari", "~> 0.14.1")
36
- # s.add_development_dependency("jruby-openssl", ">= 0.7.3")
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)
@@ -120,8 +120,6 @@ module CouchRest
120
120
  def load_from_database(db = database, id = nil)
121
121
  id ||= self['_id']
122
122
  db.get(id)
123
- rescue RestClient::ResourceNotFound
124
- nil
125
123
  end
126
124
 
127
125
  # Calculate and update the checksum of the Design document.
@@ -58,10 +58,16 @@ module CouchRest
58
58
  # are no results.
59
59
  def rows
60
60
  return @rows if @rows
61
- if execute && result['rows']
62
- @rows ||= result['rows'].map{|v| ViewRow.new(v, model)}
63
- else
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
- @docs ||= rows.map{|r| r.doc}
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 "Database must be defined in model or view!" if use_database.nil?
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 = 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
- return model.build_from_database(self['doc']) if self['doc']
559
- doc_id = (value.is_a?(Hash) && value['_id']) ? value['_id'] : self.id
560
- doc_id ? model.get(doc_id) : nil
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
- begin
37
- get!(id, db)
38
- rescue
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 id
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::Database.class_eval do
6
+ module CouchRest::Model
7
+ module Support
8
+ module Database
7
9
 
8
- def delete!
9
- Thread.current[:couchrest_design_cache] = { }
10
- CouchRest.delete @root
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 RestClient Conflict error:
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 setup(model)
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
 
@@ -3,7 +3,7 @@ require 'person'
3
3
  require 'money'
4
4
 
5
5
  class Course < CouchRest::Model::Base
6
- use_database TEST_SERVER.default_database
6
+ use_database DB
7
7
 
8
8
  property :title, String
9
9
  property :subtitle, String, :allow_blank => false
@@ -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 TEST_SERVER.default_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!(:proxy_owner_method).twice.and_return('company')
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