correlate 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +23 -0
- data/LICENSE +20 -0
- data/README.rdoc +137 -0
- data/Rakefile +48 -0
- data/correlate.gemspec +101 -0
- data/lib/correlate.rb +97 -0
- data/lib/correlate/correlation.rb +116 -0
- data/lib/correlate/links.rb +89 -0
- data/lib/correlate/relationships.rb +36 -0
- data/lib/correlate/relationships/active_record.rb +146 -0
- data/lib/correlate/relationships/active_record/collection_proxy.rb +32 -0
- data/lib/correlate/relationships/couchrest.rb +171 -0
- data/lib/correlate/validator.rb +49 -0
- data/spec/active_record_spec.rb +30 -0
- data/spec/activerecord_helper.rb +17 -0
- data/spec/correlate_spec.rb +132 -0
- data/spec/fixtures/article.rb +8 -0
- data/spec/fixtures/blank_doc.rb +4 -0
- data/spec/fixtures/comment.rb +11 -0
- data/spec/fixtures/course.rb +5 -0
- data/spec/fixtures/crawler.rb +6 -0
- data/spec/fixtures/news_feed.rb +13 -0
- data/spec/fixtures/note.rb +2 -0
- data/spec/fixtures/person.rb +11 -0
- data/spec/fixtures/project.rb +2 -0
- data/spec/fixtures/reader.rb +11 -0
- data/spec/fixtures/student.rb +11 -0
- data/spec/links_spec.rb +27 -0
- data/spec/relationships_spec.rb +18 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +41 -0
- data/spec/validation_spec.rb +38 -0
- metadata +144 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
module Correlate
|
2
|
+
class Validator < ::CouchRest::Validation::GenericValidator
|
3
|
+
|
4
|
+
def initialize( field_name, options = {} )
|
5
|
+
super
|
6
|
+
@field_name, @options = field_name, options
|
7
|
+
end
|
8
|
+
|
9
|
+
def call( target )
|
10
|
+
results = []
|
11
|
+
|
12
|
+
target.class.correlations.each do |correlation|
|
13
|
+
case correlation.type
|
14
|
+
when :some
|
15
|
+
results << validate_some( correlation, target )
|
16
|
+
when :a
|
17
|
+
results << validate_a( correlation, target )
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
!results.any? { |r| r == false }
|
22
|
+
end
|
23
|
+
|
24
|
+
def validate_some( correlation, target )
|
25
|
+
results = true
|
26
|
+
|
27
|
+
case correlation.requires
|
28
|
+
when Fixnum
|
29
|
+
unless target.send( correlation.name, true ).size >= correlation.requires
|
30
|
+
target.errors.add( correlation.name, "Requires at least #{correlation.requires} #{correlation.name}" )
|
31
|
+
results = false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
results
|
36
|
+
end
|
37
|
+
|
38
|
+
def validate_a( correlation, target )
|
39
|
+
results = true
|
40
|
+
|
41
|
+
if correlation.required && target.send( correlation.name ).nil?
|
42
|
+
target.errors.add( correlation.name, "is required" )
|
43
|
+
results = false
|
44
|
+
end
|
45
|
+
|
46
|
+
results
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Correlate, ActiveRecord do
|
4
|
+
fixtures :article, :comment
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@article = Article.create( :title => 'Correlations in C' )
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should have an empty association" do
|
11
|
+
@article.comments.should be_empty
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should accept a new associated document" do
|
15
|
+
comment = Comment.create( :comment => 'awesome' )
|
16
|
+
@article.comments << comment
|
17
|
+
|
18
|
+
@article.comments.should == [ comment ]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should be reciprocal" do
|
22
|
+
comment = Comment.create( :comment => 'extreme' )
|
23
|
+
comment.article = @article
|
24
|
+
|
25
|
+
comment.article.should == @article
|
26
|
+
comment.save
|
27
|
+
|
28
|
+
Comment.get( comment.id ).article.should == @article
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'activerecord'
|
2
|
+
|
3
|
+
# Setup connection
|
4
|
+
def reset_test_sqlitedb!
|
5
|
+
ActiveRecord::Base.connection.disconnect! rescue nil
|
6
|
+
ActiveRecord::Base.establish_connection(
|
7
|
+
:adapter => 'sqlite3',
|
8
|
+
:database => ':memory:'
|
9
|
+
)
|
10
|
+
|
11
|
+
ActiveRecord::Schema.verbose = false
|
12
|
+
ActiveRecord::Schema.define do
|
13
|
+
create_table :articles do |t|
|
14
|
+
t.string 'title'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Correlate do
|
4
|
+
fixtures :person, :reader, :news_feed, :crawler
|
5
|
+
|
6
|
+
describe "extends classes" do
|
7
|
+
it "to track correlations" do
|
8
|
+
Person.correlations.should_not be_empty
|
9
|
+
|
10
|
+
correlation = Person.correlations.first
|
11
|
+
correlation.should be_a_kind_of( Correlate::Correlation )
|
12
|
+
correlation.type.should == :some
|
13
|
+
correlation.name.should == :people
|
14
|
+
correlation.target.should == 'Person'
|
15
|
+
correlation.source.should == Person
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should define a view for looking up rels" do
|
19
|
+
Person.should have_view('by_rel')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "to self" do
|
24
|
+
before(:each) do
|
25
|
+
@person = Person.new
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should have an empty array" do
|
29
|
+
@person.people.should be_a_kind_of( Array )
|
30
|
+
@person.people.should be_empty
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should accept new associations" do
|
34
|
+
person = Person.create :name => 'John'
|
35
|
+
@person.people << person
|
36
|
+
|
37
|
+
@person.links.should == [{ 'rel' => 'person', 'href' => person.id }]
|
38
|
+
@person.save!
|
39
|
+
|
40
|
+
Person.get( @person.id ).links.should == [{ 'rel' => 'person', 'href' => person.id }]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should load objects from associations" do
|
44
|
+
person = Person.create :name => 'Jack'
|
45
|
+
@person.people << person
|
46
|
+
@person.save!
|
47
|
+
|
48
|
+
@person.people.should == [ person ]
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should have the raw associations" do
|
52
|
+
person = Person.create :name => 'Jack'
|
53
|
+
@person.people << person
|
54
|
+
@person.save!
|
55
|
+
|
56
|
+
@person.people( true ).should == [{'rel' => 'person', 'href' => person.id }]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "to some others" do
|
61
|
+
before(:each) do
|
62
|
+
@reader = Reader.new
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should have an empty array" do
|
66
|
+
@reader.news_feeds.should be_empty
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should accept new associations" do
|
70
|
+
feed = NewsFeed.create :url => 'http://planet.couchdb.com/atom.xml'
|
71
|
+
@reader.news_feeds << feed
|
72
|
+
|
73
|
+
@reader.links.should == [{ 'rel' => 'news_feed', 'href' => feed.id }]
|
74
|
+
@reader.save!
|
75
|
+
|
76
|
+
Reader.get( @reader.id ).links.should == [{ 'rel' => 'news_feed', 'href' => feed.id }]
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should load objects from associations" do
|
80
|
+
feed = NewsFeed.create :url => 'http://planet.couchdb.com/atom.xml'
|
81
|
+
@reader.news_feeds << feed
|
82
|
+
@reader.save!
|
83
|
+
|
84
|
+
@reader.news_feeds.should == [ feed ]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should have access to the raw accosiations" do
|
88
|
+
feed = NewsFeed.create :url => 'http://planet.couchdb.com/atom.xml'
|
89
|
+
@reader.news_feeds << feed
|
90
|
+
@reader.save!
|
91
|
+
|
92
|
+
@reader.news_feeds( true ).should == [{ 'rel' => 'news_feed', 'href' => feed.id }]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "to another" do
|
97
|
+
before(:each) do
|
98
|
+
@feed = NewsFeed.new( :url => 'http://planet.couchdb.com/atom.xml' )
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should have a nil instance" do
|
102
|
+
@feed.crawler.should be_nil
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should accept a new instance" do
|
106
|
+
crawler = Crawler.create :host => 'foo.example.com'
|
107
|
+
@feed.crawler = crawler
|
108
|
+
|
109
|
+
@feed.links.should == [{ 'rel' => 'crawler', 'href' => crawler.id }]
|
110
|
+
@feed.save!
|
111
|
+
|
112
|
+
NewsFeed.get( @feed.id ).links.should == [{ 'rel' => 'crawler', 'href' => crawler.id }]
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should load the object from the association" do
|
116
|
+
crawler = Crawler.create :host => 'foo.example.com'
|
117
|
+
@feed.crawler = crawler
|
118
|
+
@feed.save!
|
119
|
+
|
120
|
+
@feed.crawler.should == crawler
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should give access to the raw association" do
|
124
|
+
crawler = Crawler.create :host => 'foo.example.com'
|
125
|
+
@feed.crawler = crawler
|
126
|
+
@feed.save!
|
127
|
+
|
128
|
+
@feed.crawler( true ).should == { 'rel' => 'crawler', 'href' => crawler.id }
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
data/spec/links_spec.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Correlate::Links do
|
4
|
+
fixtures :person
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@blank = Correlate::Links.new( Person )
|
8
|
+
|
9
|
+
@links = Correlate::Links.new( Person )
|
10
|
+
@links << { 'rel' => 'foo', 'href' => 'bar' }
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be able to find by rel" do
|
14
|
+
@links.rel( 'foo' ).should == [{ 'rel' => 'foo', 'href' => 'bar' }]
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should be able to replace by rel" do
|
18
|
+
@links.replace({ 'rel' => 'foo', 'href' => 'baz' })
|
19
|
+
|
20
|
+
@links.should == [{ 'rel' => 'foo', 'href' => 'baz' }]
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be able to delete by rel" do
|
24
|
+
@links.delete({ 'rel' => 'foo', 'href' => 'bar' })
|
25
|
+
@links.should be_empty
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Correlate::Relationships do
|
4
|
+
fixtures :blank_doc
|
5
|
+
|
6
|
+
it "should be able to configure a class" do
|
7
|
+
relationships = lambda {
|
8
|
+
some :foo
|
9
|
+
}
|
10
|
+
|
11
|
+
Correlate::Relationships.configure!( BlankDoc, &relationships )
|
12
|
+
|
13
|
+
link_property = BlankDoc.properties.detect { |p| p.name == 'links' }
|
14
|
+
link_property.should_not be_nil
|
15
|
+
link_property.type.should == 'Correlate::Links'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'correlate'
|
4
|
+
require 'spec'
|
5
|
+
require 'spec/autorun'
|
6
|
+
|
7
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
8
|
+
require 'couchrest'
|
9
|
+
require 'activerecord_helper'
|
10
|
+
|
11
|
+
unless defined?( COUCHHOST )
|
12
|
+
COUCHHOST = "http://127.0.0.1:5984"
|
13
|
+
TESTDB = 'correlate-test'
|
14
|
+
TEST_SERVER = CouchRest.new
|
15
|
+
TEST_SERVER.default_database = TESTDB
|
16
|
+
DB = TEST_SERVER.database(TESTDB)
|
17
|
+
end
|
18
|
+
|
19
|
+
Spec::Runner.configure do |config|
|
20
|
+
config.before(:suite) do
|
21
|
+
reset_test_sqlitedb!
|
22
|
+
end
|
23
|
+
|
24
|
+
config.before(:all) do
|
25
|
+
reset_test_couchdb!
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def fixtures( *args )
|
30
|
+
args.each do |file|
|
31
|
+
file = file.to_s
|
32
|
+
if File.exists?( File.join( File.dirname(__FILE__), 'fixtures', "#{file}.rb" ) )
|
33
|
+
require File.join( File.dirname(__FILE__), 'fixtures', file )
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def reset_test_couchdb!
|
39
|
+
DB.recreate! rescue nil
|
40
|
+
DB
|
41
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Correlate do
|
4
|
+
describe "validations for 'some'" do
|
5
|
+
fixtures :student, :course
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@student = Student.new
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should be enforced" do
|
12
|
+
@student.should_not be_valid
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should be met" do
|
16
|
+
@student.enlistments << Course.create( :name => 'B.Sc Foo' )
|
17
|
+
@student.should be_valid
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "validations for 'a'" do
|
22
|
+
fixtures :comment, :article
|
23
|
+
|
24
|
+
before(:each) do
|
25
|
+
@comment = Comment.new
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should be enforced" do
|
29
|
+
@comment.should_not be_valid
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should be met" do
|
33
|
+
article = Article.create( :title => 'Validating the system' )
|
34
|
+
@comment.article = article
|
35
|
+
@comment.should be_valid
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|