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