addywaddy-couch_surfer 0.0.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.
- data/LICENSE +0 -0
- data/README.md +73 -0
- data/Rakefile +67 -0
- data/lib/couch_surfer/associations.rb +57 -0
- data/lib/couch_surfer/model.rb +620 -0
- data/lib/couch_surfer/validations.rb +51 -0
- data/lib/couch_surfer.rb +9 -0
- data/spec/fixtures/attachments/README +3 -0
- data/spec/fixtures/attachments/couchdb.png +0 -0
- data/spec/fixtures/attachments/test.html +11 -0
- data/spec/fixtures/views/lib.js +3 -0
- data/spec/fixtures/views/test_view/lib.js +3 -0
- data/spec/fixtures/views/test_view/only-map.js +4 -0
- data/spec/fixtures/views/test_view/test-map.js +3 -0
- data/spec/fixtures/views/test_view/test-reduce.js +3 -0
- data/spec/lib/associations_spec.rb +74 -0
- data/spec/lib/model_spec.rb +883 -0
- data/spec/lib/validations_spec.rb +93 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +27 -0
- metadata +105 -0
data/LICENSE
ADDED
File without changes
|
data/README.md
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
CouchSurfer
|
2
|
+
===========
|
3
|
+
|
4
|
+
Description
|
5
|
+
-----------
|
6
|
+
CouchSurfer is an extraction of CouchRest::Model from the excellent [CouchRest](http://github.com/jchris/couchrest/ "CouchRest") gem by J. Chris Anderson.
|
7
|
+
|
8
|
+
Features
|
9
|
+
--------
|
10
|
+
- ORM (Extracted from CouchRest::Model)
|
11
|
+
- Associations
|
12
|
+
- `has_ many`
|
13
|
+
- `belongs_to`
|
14
|
+
|
15
|
+
- Validations
|
16
|
+
- All validations from the [Validatable](http://github.com/jrun/validatable/ "Validatable") gem
|
17
|
+
- `validates_uniqueness_of`
|
18
|
+
|
19
|
+
Examples
|
20
|
+
--------
|
21
|
+
class Account
|
22
|
+
include CouchSurfer::Model
|
23
|
+
include CouchSurfer::Associations
|
24
|
+
|
25
|
+
key_accessor :name
|
26
|
+
|
27
|
+
# Will use the Project.by_account_id view with {:key => account_instance.id}
|
28
|
+
has_many :projects
|
29
|
+
|
30
|
+
# Uses a custom view and key
|
31
|
+
has_many :employees, :view => {:name => :by_account_id_and_email,
|
32
|
+
:query => lambda{ {:startkey => [id, nil], :endkey => [id, {}]} }}
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
class Project
|
37
|
+
include CouchSurfer::Model
|
38
|
+
include CouchSurfer::Associations
|
39
|
+
|
40
|
+
key_accessor :name, :account_id
|
41
|
+
|
42
|
+
belongs_to :account
|
43
|
+
|
44
|
+
view_by :account_id
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
class Employee
|
49
|
+
include CouchSurfer::Model
|
50
|
+
include CouchSurfer::Associations
|
51
|
+
include CouchSurfer::Validations
|
52
|
+
|
53
|
+
key_accessor :email, :account_id
|
54
|
+
belongs_to :account
|
55
|
+
|
56
|
+
view_by :account_id, :email
|
57
|
+
view_by :name
|
58
|
+
|
59
|
+
validates_presence_of :name
|
60
|
+
validates_format_of :email,
|
61
|
+
:with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
|
62
|
+
validates_length_of :postcode, :is => 7, :message => "not the correct length"
|
63
|
+
|
64
|
+
# Will use the Employee.by_name view with {:key => employee_instance.name}
|
65
|
+
validates_uniqueness_of :name, :message => "No two Beatles have the same name"
|
66
|
+
|
67
|
+
# Uses a custom view and key
|
68
|
+
validates_uniqueness_of :email, :view => {:name => :by_account_id_and_email,
|
69
|
+
:query => lambda{ {:key => [account_id, email]} }}, :message => "Already taken!"
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
Please check out the specs as well :)
|
data/Rakefile
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require "rake/rdoctask"
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
require File.join(File.expand_path(File.dirname(__FILE__)),'lib','couch_surfer')
|
5
|
+
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'spec/rake/spectask'
|
9
|
+
rescue LoadError
|
10
|
+
puts <<-EOS
|
11
|
+
To use rspec for testing you must install rspec gem:
|
12
|
+
gem install rspec
|
13
|
+
EOS
|
14
|
+
exit(0)
|
15
|
+
end
|
16
|
+
|
17
|
+
spec = Gem::Specification.new do |s|
|
18
|
+
s.name = "couch_surfer"
|
19
|
+
s.version = CouchSurfer::VERSION
|
20
|
+
s.date = "2009-01-22"
|
21
|
+
s.summary = "ORM based on CouchRest::Model"
|
22
|
+
s.email = "jchris@apache.org"
|
23
|
+
s.homepage = "http://github.com/addywaddy/couchsurfer"
|
24
|
+
s.description = "CouchSurfer provides an ORM for CouchDB, as well as supporting association and validation declarations."
|
25
|
+
s.has_rdoc = true
|
26
|
+
s.authors = ["Adam Groves"]
|
27
|
+
s.files = %w( LICENSE README.md Rakefile ) +
|
28
|
+
Dir["{lib,spec}/**/*"] -
|
29
|
+
Dir["spec/tmp"]
|
30
|
+
s.extra_rdoc_files = %w( README.md LICENSE )
|
31
|
+
s.require_path = "lib"
|
32
|
+
s.add_dependency("json", ">= 1.1.2")
|
33
|
+
s.add_dependency("rest-client", ">= 0.5")
|
34
|
+
s.add_dependency('jchris-couchrest', ">= 0.12.2")
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
desc "create .gemspec file (useful for github)"
|
39
|
+
task :gemspec do
|
40
|
+
filename = "#{spec.name}.gemspec"
|
41
|
+
File.open(filename, "w") do |f|
|
42
|
+
f.puts spec.to_ruby
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "Run all specs"
|
47
|
+
Spec::Rake::SpecTask.new('spec') do |t|
|
48
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "Print specdocs"
|
52
|
+
Spec::Rake::SpecTask.new(:doc) do |t|
|
53
|
+
t.spec_opts = ["--format", "specdoc"]
|
54
|
+
t.spec_files = FileList['spec/*_spec.rb']
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "Generate the rdoc"
|
58
|
+
Rake::RDocTask.new do |rdoc|
|
59
|
+
files = ["README.rdoc", "LICENSE", "lib/**/*.rb"]
|
60
|
+
rdoc.rdoc_files.add(files)
|
61
|
+
rdoc.main = "README.rdoc"
|
62
|
+
rdoc.title = "CouchRest: Ruby CouchDB, close to the metal"
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "Run the rspec"
|
66
|
+
task :default => :spec
|
67
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'extlib'
|
3
|
+
|
4
|
+
module CouchSurfer
|
5
|
+
module Associations
|
6
|
+
module ClassMethods
|
7
|
+
def has_many *args
|
8
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
9
|
+
children = args.first
|
10
|
+
define_method children do |*args|
|
11
|
+
query_params = args.last.is_a?(Hash) ? args.pop : nil
|
12
|
+
name = ::Extlib::Inflection.camelize(children.to_s.singular)
|
13
|
+
klass = ::Extlib::Inflection.constantize(name)
|
14
|
+
if options[:view].is_a?(Hash)
|
15
|
+
view_name = options[:view][:name]
|
16
|
+
query = options[:view][:query].is_a?(Proc) ? self.instance_eval(&options[:view][:query]) : nil
|
17
|
+
end
|
18
|
+
view_name ||= "by_#{self.class.name.downcase}_id"
|
19
|
+
query ||= {:key => self.id}
|
20
|
+
klass.send(view_name, query)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def belongs_to *args
|
25
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
26
|
+
parent = args.first
|
27
|
+
# view_key = "#{parent}_id".to_sym
|
28
|
+
# if options[:identifiers]
|
29
|
+
# if options[:prepend]
|
30
|
+
# view_key = options[:identifiers] << view_key
|
31
|
+
# else
|
32
|
+
# view_key = options[:identifiers].unshift(view_key)
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
# class_eval do
|
36
|
+
# view_by *view_key
|
37
|
+
# end
|
38
|
+
define_method parent do
|
39
|
+
name = ::Extlib::Inflection.camelize(parent.to_s)
|
40
|
+
klass = ::Extlib::Inflection.constantize(name)
|
41
|
+
parent_id = self["#{parent.to_s}_id"]
|
42
|
+
if parent_id
|
43
|
+
klass.send(:get, self["#{parent.to_s}_id"])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
define_method "#{parent}=".to_sym do |parent_obj|
|
48
|
+
self["#{parent_obj.class.name.downcase}_id"] = parent_obj.id
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.included(receiver)
|
54
|
+
receiver.extend ClassMethods
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|