correlate 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,8 @@
1
+ class Article < ActiveRecord::Base
2
+
3
+ include Correlate
4
+
5
+ related_to do
6
+ some :comments, :class => 'Comment'
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ class BlankDoc < CouchRest::ExtendedDocument
2
+
3
+ include Correlate
4
+ end
@@ -0,0 +1,11 @@
1
+ class Comment < CouchRest::ExtendedDocument
2
+
3
+ use_database DB
4
+
5
+ include Correlate
6
+ include CouchRest::Validation
7
+
8
+ related_to do
9
+ a :article, :class => 'Article', :required => true
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ # Students are enlisted into courses
2
+ class Course < CouchRest::ExtendedDocument
3
+
4
+ use_database DB
5
+ end
@@ -0,0 +1,6 @@
1
+ # Responsible for updating the news feeds
2
+ class Crawler < CouchRest::ExtendedDocument
3
+
4
+ use_database DB
5
+
6
+ end
@@ -0,0 +1,13 @@
1
+ # The news feeds read by a reader, and has a crawler that updates it
2
+ class NewsFeed < CouchRest::ExtendedDocument
3
+
4
+ include Correlate
5
+
6
+ use_database DB
7
+
8
+ property :url
9
+
10
+ related_to do
11
+ a :crawler, :class => 'Crawler'
12
+ end
13
+ end
@@ -0,0 +1,2 @@
1
+ #class Note < CouchRest::ExtendedDocument
2
+ #end
@@ -0,0 +1,11 @@
1
+ # Test on a 'simple social graph'
2
+ class Person < CouchRest::ExtendedDocument
3
+
4
+ use_database DB
5
+
6
+ include Correlate
7
+
8
+ related_to do
9
+ some :people, :class => 'Person', :rel => 'person'
10
+ end
11
+ end
@@ -0,0 +1,2 @@
1
+ #class Project < ActiveRecord::Base
2
+ #end
@@ -0,0 +1,11 @@
1
+ # A reader of articles from different feeds
2
+ class Reader < CouchRest::ExtendedDocument
3
+
4
+ include Correlate
5
+
6
+ use_database DB
7
+
8
+ related_to do
9
+ some :news_feeds, :class => 'NewsFeed', :rel => 'news_feed'
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ class Student < CouchRest::ExtendedDocument
2
+
3
+ use_database DB
4
+
5
+ include Correlate
6
+ include CouchRest::Validation
7
+
8
+ related_to do
9
+ some :enlistments, :class => 'Course', :rel => 'course', :requires => 1
10
+ end
11
+ end
@@ -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
+
@@ -0,0 +1 @@
1
+ --color
@@ -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