couchrest_model 1.0.0.beta7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/LICENSE +176 -0
  2. data/README.md +320 -0
  3. data/Rakefile +71 -0
  4. data/THANKS.md +19 -0
  5. data/examples/model/example.rb +144 -0
  6. data/history.txt +180 -0
  7. data/lib/couchrest/model.rb +10 -0
  8. data/lib/couchrest/model/associations.rb +207 -0
  9. data/lib/couchrest/model/attribute_protection.rb +74 -0
  10. data/lib/couchrest/model/attributes.rb +75 -0
  11. data/lib/couchrest/model/base.rb +111 -0
  12. data/lib/couchrest/model/callbacks.rb +27 -0
  13. data/lib/couchrest/model/casted_array.rb +39 -0
  14. data/lib/couchrest/model/casted_model.rb +68 -0
  15. data/lib/couchrest/model/class_proxy.rb +122 -0
  16. data/lib/couchrest/model/collection.rb +260 -0
  17. data/lib/couchrest/model/design_doc.rb +126 -0
  18. data/lib/couchrest/model/document_queries.rb +82 -0
  19. data/lib/couchrest/model/errors.rb +23 -0
  20. data/lib/couchrest/model/extended_attachments.rb +73 -0
  21. data/lib/couchrest/model/persistence.rb +141 -0
  22. data/lib/couchrest/model/properties.rb +144 -0
  23. data/lib/couchrest/model/property.rb +96 -0
  24. data/lib/couchrest/model/support/couchrest.rb +19 -0
  25. data/lib/couchrest/model/support/hash.rb +9 -0
  26. data/lib/couchrest/model/typecast.rb +170 -0
  27. data/lib/couchrest/model/validations.rb +68 -0
  28. data/lib/couchrest/model/validations/casted_model.rb +14 -0
  29. data/lib/couchrest/model/validations/locale/en.yml +5 -0
  30. data/lib/couchrest/model/validations/uniqueness.rb +45 -0
  31. data/lib/couchrest/model/views.rb +167 -0
  32. data/lib/couchrest_model.rb +56 -0
  33. data/spec/couchrest/assocations_spec.rb +213 -0
  34. data/spec/couchrest/attachment_spec.rb +148 -0
  35. data/spec/couchrest/attribute_protection_spec.rb +153 -0
  36. data/spec/couchrest/base_spec.rb +463 -0
  37. data/spec/couchrest/casted_model_spec.rb +424 -0
  38. data/spec/couchrest/casted_spec.rb +75 -0
  39. data/spec/couchrest/class_proxy_spec.rb +132 -0
  40. data/spec/couchrest/inherited_spec.rb +40 -0
  41. data/spec/couchrest/persistence_spec.rb +409 -0
  42. data/spec/couchrest/property_spec.rb +804 -0
  43. data/spec/couchrest/subclass_spec.rb +99 -0
  44. data/spec/couchrest/validations.rb +73 -0
  45. data/spec/couchrest/view_spec.rb +463 -0
  46. data/spec/fixtures/attachments/README +3 -0
  47. data/spec/fixtures/attachments/couchdb.png +0 -0
  48. data/spec/fixtures/attachments/test.html +11 -0
  49. data/spec/fixtures/base.rb +139 -0
  50. data/spec/fixtures/more/article.rb +35 -0
  51. data/spec/fixtures/more/card.rb +17 -0
  52. data/spec/fixtures/more/cat.rb +19 -0
  53. data/spec/fixtures/more/course.rb +25 -0
  54. data/spec/fixtures/more/event.rb +8 -0
  55. data/spec/fixtures/more/invoice.rb +14 -0
  56. data/spec/fixtures/more/person.rb +9 -0
  57. data/spec/fixtures/more/question.rb +7 -0
  58. data/spec/fixtures/more/service.rb +10 -0
  59. data/spec/fixtures/more/user.rb +22 -0
  60. data/spec/fixtures/views/lib.js +3 -0
  61. data/spec/fixtures/views/test_view/lib.js +3 -0
  62. data/spec/fixtures/views/test_view/only-map.js +4 -0
  63. data/spec/fixtures/views/test_view/test-map.js +3 -0
  64. data/spec/fixtures/views/test_view/test-reduce.js +3 -0
  65. data/spec/spec.opts +5 -0
  66. data/spec/spec_helper.rb +48 -0
  67. data/utils/remap.rb +27 -0
  68. data/utils/subset.rb +30 -0
  69. metadata +232 -0
@@ -0,0 +1,3 @@
1
+ This is an example README file.
2
+
3
+ More of the README, whee.
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Test</title>
5
+ </head>
6
+ <body>
7
+ <p>
8
+ Test
9
+ </p>
10
+ </body>
11
+ </html>
@@ -0,0 +1,139 @@
1
+ class WithDefaultValues < CouchRest::Model::Base
2
+ use_database TEST_SERVER.default_database
3
+ property :preset, Object, :default => {:right => 10, :top_align => false}
4
+ property :set_by_proc, Time, :default => Proc.new{Time.now}
5
+ property :tags, [String], :default => []
6
+ property :read_only_with_default, :default => 'generic', :read_only => true
7
+ property :default_false, TrueClass, :default => false
8
+ property :name
9
+ timestamps!
10
+ end
11
+
12
+ class WithSimplePropertyType < CouchRest::Model::Base
13
+ use_database TEST_SERVER.default_database
14
+ property :name, String
15
+ property :preset, String, :default => 'none'
16
+ property :tags, [String]
17
+ timestamps!
18
+ end
19
+
20
+ class WithCallBacks < CouchRest::Model::Base
21
+ use_database TEST_SERVER.default_database
22
+ property :name
23
+ property :run_before_validate
24
+ property :run_after_validate
25
+ property :run_before_save
26
+ property :run_after_save
27
+ property :run_before_create
28
+ property :run_after_create
29
+ property :run_before_update
30
+ property :run_after_update
31
+
32
+ before_validate do |object|
33
+ object.run_before_validate = true
34
+ end
35
+ after_validate do |object|
36
+ object.run_after_validate = true
37
+ end
38
+ before_save do |object|
39
+ object.run_before_save = true
40
+ end
41
+ after_save do |object|
42
+ object.run_after_save = true
43
+ end
44
+ before_create do |object|
45
+ object.run_before_create = true
46
+ end
47
+ after_create do |object|
48
+ object.run_after_create = true
49
+ end
50
+ before_update do |object|
51
+ object.run_before_update = true
52
+ end
53
+ after_update do |object|
54
+ object.run_after_update = true
55
+ end
56
+
57
+ property :run_one
58
+ property :run_two
59
+ property :run_three
60
+
61
+ before_save :run_one_method, :run_two_method do |object|
62
+ object.run_three = true
63
+ end
64
+ def run_one_method
65
+ self.run_one = true
66
+ end
67
+ def run_two_method
68
+ self.run_two = true
69
+ end
70
+
71
+ attr_accessor :run_it
72
+ property :conditional_one
73
+ property :conditional_two
74
+
75
+ before_save :conditional_one_method, :conditional_two_method, :if => proc { self.run_it }
76
+ def conditional_one_method
77
+ self.conditional_one = true
78
+ end
79
+ def conditional_two_method
80
+ self.conditional_two = true
81
+ end
82
+ end
83
+
84
+ class WithTemplateAndUniqueID < CouchRest::Model::Base
85
+ use_database TEST_SERVER.default_database
86
+ unique_id do |model|
87
+ model['important-field']
88
+ end
89
+ property :preset, :default => 'value'
90
+ property :has_no_default
91
+ end
92
+
93
+ class WithGetterAndSetterMethods < CouchRest::Model::Base
94
+ use_database TEST_SERVER.default_database
95
+
96
+ property :other_arg
97
+ def arg
98
+ other_arg
99
+ end
100
+
101
+ def arg=(value)
102
+ self.other_arg = "foo-#{value}"
103
+ end
104
+ end
105
+
106
+ class WithAfterInitializeMethod < CouchRest::Model::Base
107
+ use_database TEST_SERVER.default_database
108
+
109
+ property :some_value
110
+
111
+ def after_initialize
112
+ self.some_value ||= "value"
113
+ end
114
+
115
+ end
116
+
117
+ class WithUniqueValidation < CouchRest::Model::Base
118
+ use_database DB
119
+ property :title
120
+ validates_uniqueness_of :title
121
+ end
122
+ class WithUniqueValidationProxy < CouchRest::Model::Base
123
+ use_database DB
124
+ property :title
125
+ validates_uniqueness_of :title, :proxy => 'proxy'
126
+ end
127
+ class WithUniqueValidationView < CouchRest::Model::Base
128
+ use_database DB
129
+ attr_accessor :code
130
+ unique_id :code
131
+ def code
132
+ self["_id"] ||= @code
133
+ end
134
+ property :title
135
+
136
+ validates_uniqueness_of :code, :view => 'all'
137
+ end
138
+
139
+
@@ -0,0 +1,35 @@
1
+ class Article < CouchRest::Model::Base
2
+ use_database DB
3
+ unique_id :slug
4
+
5
+ provides_collection :article_details, 'Article', 'by_date', :descending => true, :include_docs => true
6
+ view_by :date, :descending => true
7
+ view_by :user_id, :date
8
+
9
+ view_by :tags,
10
+ :map =>
11
+ "function(doc) {
12
+ if (doc['couchrest-type'] == 'Article' && doc.tags) {
13
+ doc.tags.forEach(function(tag){
14
+ emit(tag, 1);
15
+ });
16
+ }
17
+ }",
18
+ :reduce =>
19
+ "function(keys, values, rereduce) {
20
+ return sum(values);
21
+ }"
22
+
23
+ property :date, Date
24
+ property :slug, :read_only => true
25
+ property :title
26
+ property :tags, [String]
27
+
28
+ timestamps!
29
+
30
+ before_save :generate_slug_from_title
31
+
32
+ def generate_slug_from_title
33
+ self['slug'] = title.downcase.gsub(/[^a-z0-9]/,'-').squeeze('-').gsub(/^\-|\-$/,'') if new?
34
+ end
35
+ end
@@ -0,0 +1,17 @@
1
+ class Card < CouchRest::Model::Base
2
+ # Set the default database to use
3
+ use_database DB
4
+
5
+ # Official Schema
6
+ property :first_name
7
+ property :last_name, :alias => :family_name
8
+ property :read_only_value, :read_only => true
9
+ property :cast_alias, Person, :alias => :calias
10
+
11
+
12
+ timestamps!
13
+
14
+ # Validation
15
+ validates_presence_of :first_name
16
+
17
+ end
@@ -0,0 +1,19 @@
1
+
2
+ class CatToy < Hash
3
+ include ::CouchRest::Model::CastedModel
4
+
5
+ property :name
6
+
7
+ validates_presence_of :name
8
+ end
9
+
10
+ class Cat < CouchRest::Model::Base
11
+ # Set the default database to use
12
+ use_database DB
13
+
14
+ property :name, :accessible => true
15
+ property :toys, [CatToy], :default => [], :accessible => true
16
+ property :favorite_toy, CatToy, :accessible => true
17
+ property :number
18
+ end
19
+
@@ -0,0 +1,25 @@
1
+ require File.join(FIXTURE_PATH, 'more', 'question')
2
+ require File.join(FIXTURE_PATH, 'more', 'person')
3
+
4
+ class Course < CouchRest::Model::Base
5
+ use_database TEST_SERVER.default_database
6
+
7
+ property :title, String
8
+ property :questions, [Question]
9
+ property :professor, Person
10
+ property :participants, [Object]
11
+ property :ends_at, Time
12
+ property :estimate, Float
13
+ property :hours, Integer
14
+ property :profit, BigDecimal
15
+ property :started_on, :type => Date
16
+ property :updated_at, :type => DateTime
17
+ property :active, :type => TrueClass
18
+ property :very_active, :type => TrueClass
19
+ property :klass, :type => Class
20
+
21
+ view_by :title
22
+ view_by :title, :active
23
+ view_by :dept, :ducktype => true
24
+
25
+ end
@@ -0,0 +1,8 @@
1
+ class Event < CouchRest::Model::Base
2
+ use_database DB
3
+
4
+ property :subject
5
+ property :occurs_at, Time, :init_method => 'parse'
6
+ property :end_date, Date, :init_method => 'parse'
7
+
8
+ end
@@ -0,0 +1,14 @@
1
+ class Invoice < CouchRest::Model::Base
2
+ # Set the default database to use
3
+ use_database DB
4
+
5
+ # Official Schema
6
+ property :client_name
7
+ property :employee_name
8
+ property :location
9
+
10
+ # Validation
11
+ validates_presence_of :client_name, :employee_name
12
+ validates_presence_of :location, :message => "Hey stupid!, you forgot the location"
13
+
14
+ end
@@ -0,0 +1,9 @@
1
+ class Person < Hash
2
+ include ::CouchRest::Model::CastedModel
3
+ property :pet, Cat
4
+ property :name, [String]
5
+
6
+ def last_name
7
+ name.last
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ class Question < Hash
2
+ include ::CouchRest::Model::CastedModel
3
+
4
+ property :q
5
+ property :a
6
+
7
+ end
@@ -0,0 +1,10 @@
1
+ class Service < CouchRest::Model::Base
2
+ # Set the default database to use
3
+ use_database DB
4
+
5
+ # Official Schema
6
+ property :name
7
+ property :price, Integer
8
+
9
+ validates_length_of :name, :minimum => 4, :maximum => 20
10
+ end
@@ -0,0 +1,22 @@
1
+ class User < CouchRest::Model::Base
2
+ # Set the default database to use
3
+ use_database DB
4
+ property :name, :accessible => true
5
+ property :admin # this will be automatically protected
6
+ end
7
+
8
+ class SpecialUser < CouchRest::Model::Base
9
+ # Set the default database to use
10
+ use_database DB
11
+ property :name # this will not be protected
12
+ property :admin, :protected => true
13
+ end
14
+
15
+ # There are two modes of protection
16
+ # 1) Declare accessible poperties, assume all the rest are protected
17
+ # property :name, :accessible => true
18
+ # property :admin # this will be automatically protected
19
+ #
20
+ # 2) Declare protected properties, assume all the rest are accessible
21
+ # property :name # this will not be protected
22
+ # property :admin, :protected => true
@@ -0,0 +1,3 @@
1
+ function globalLib() {
2
+ return "fixture";
3
+ };
@@ -0,0 +1,3 @@
1
+ function justThisView() {
2
+ return "fixture";
3
+ };
@@ -0,0 +1,4 @@
1
+ function(doc) {
2
+ //include-lib
3
+ emit(null, null);
4
+ };
@@ -0,0 +1,3 @@
1
+ function(doc) {
2
+ emit(null, null);
3
+ };
@@ -0,0 +1,3 @@
1
+ function(ks,vs,co) {
2
+ return vs.length;
3
+ };
data/spec/spec.opts ADDED
@@ -0,0 +1,5 @@
1
+ --colour
2
+ --format
3
+ progress
4
+ --loadby
5
+ mtime
@@ -0,0 +1,48 @@
1
+ require "rubygems"
2
+ require "spec" # Satisfies Autotest and anyone else not using the Rake tasks
3
+
4
+ require File.join(File.dirname(__FILE__), '..','lib','couchrest_model')
5
+ # check the following file to see how to use the spec'd features.
6
+
7
+ unless defined?(FIXTURE_PATH)
8
+ FIXTURE_PATH = File.join(File.dirname(__FILE__), '/fixtures')
9
+ SCRATCH_PATH = File.join(File.dirname(__FILE__), '/tmp')
10
+
11
+ COUCHHOST = "http://127.0.0.1:5984"
12
+ TESTDB = 'couchrest-model-test'
13
+ TEST_SERVER = CouchRest.new
14
+ TEST_SERVER.default_database = TESTDB
15
+ DB = TEST_SERVER.database(TESTDB)
16
+ end
17
+
18
+ class Basic < CouchRest::Model::Base
19
+ use_database TEST_SERVER.default_database
20
+ end
21
+
22
+ def reset_test_db!
23
+ DB.recreate! rescue nil
24
+ DB
25
+ end
26
+
27
+ Spec::Runner.configure do |config|
28
+ config.before(:all) { reset_test_db! }
29
+
30
+ config.after(:all) do
31
+ cr = TEST_SERVER
32
+ test_dbs = cr.databases.select { |db| db =~ /^#{TESTDB}/ }
33
+ test_dbs.each do |db|
34
+ cr.database(db).delete! rescue nil
35
+ end
36
+ end
37
+ end
38
+
39
+ def couchdb_lucene_available?
40
+ lucene_path = "http://localhost:5985/"
41
+ url = URI.parse(lucene_path)
42
+ req = Net::HTTP::Get.new(url.path)
43
+ res = Net::HTTP.new(url.host, url.port).start { |http| http.request(req) }
44
+ true
45
+ rescue Exception => e
46
+ false
47
+ end
48
+
data/utils/remap.rb ADDED
@@ -0,0 +1,27 @@
1
+ require 'rubygems'
2
+ require 'couchrest'
3
+
4
+ # set the source db and map view
5
+ source = CouchRest.new("http://127.0.0.1:5984").database('source-db')
6
+ source_view = 'mydesign/view-map'
7
+
8
+ # set the target db
9
+ target = CouchRest.new("http://127.0.0.1:5984").database('target-db')
10
+
11
+
12
+ pager = CouchRest::Pager.new(source)
13
+
14
+ # pager will yield once per uniq key in the source view
15
+
16
+ pager.key_reduce(source_view, 10000) do |key, values|
17
+ # create a doc from the key and the values
18
+ example_doc = {
19
+ :key => key,
20
+ :values => values.uniq
21
+ }
22
+
23
+ target.save(example_doc)
24
+
25
+ # keep us up to date with progress
26
+ puts k if (rand > 0.9)
27
+ end