couchrest_model 2.0.4 → 2.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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