correlate 0.1.0
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/.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
|