tripod 0.9.7 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/tripod/components.rb +1 -0
- data/lib/tripod/fields/standard.rb +1 -0
- data/lib/tripod/fields.rb +1 -1
- data/lib/tripod/links/linked_from.rb +19 -0
- data/lib/tripod/links/linked_to.rb +21 -0
- data/lib/tripod/links.rb +172 -0
- data/lib/tripod/version.rb +1 -1
- data/lib/tripod.rb +1 -0
- data/spec/app/models/dog.rb +17 -0
- data/spec/app/models/person.rb +3 -0
- data/spec/tripod/links_spec.rb +134 -0
- data/tripod.gemspec +2 -1
- metadata +25 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c4f4a91c3753acb50660407e1862de999314cf6
|
4
|
+
data.tar.gz: 097ab255b4abf50836e5e13844dd96ccfd74e036
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd7b93b8990be65d54c964f347420d74c2c1d2327d9356e4d32e6d831cd751fb96916788e27be8b212d25400f2e7fe0f1ee68857ff28e0601473bd89805a20ec
|
7
|
+
data.tar.gz: bda4ed335ee7b00600ffaf219805b7f725a4f59d292a7f7a9ce428df017e8bacbf554dfdc8da8a63a2e281e5aad510ecb8eba1fdface9587682887c5526863b7
|
data/lib/tripod/components.rb
CHANGED
@@ -6,6 +6,7 @@ module Tripod::Fields
|
|
6
6
|
# Set readers for the instance variables.
|
7
7
|
attr_accessor :name, :predicate, :options, :datatype, :is_uri, :multivalued
|
8
8
|
alias_method :is_uri?, :is_uri
|
9
|
+
alias_method :multivalued?, :multivalued
|
9
10
|
|
10
11
|
# Create the new field with a name and optional additional options.
|
11
12
|
#
|
data/lib/tripod/fields.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Tripod::Links
|
3
|
+
# Defines the behaviour for defined links in the resource.
|
4
|
+
class LinkedFrom
|
5
|
+
|
6
|
+
# Set readers for the instance variables.
|
7
|
+
attr_accessor :name, :incoming_field, :options, :incoming_field_name, :class_name
|
8
|
+
|
9
|
+
# Create the new link with a name and optional additional options.
|
10
|
+
def initialize(name, incoming_field_name, options = {})
|
11
|
+
@name = name
|
12
|
+
@options = options
|
13
|
+
@incoming_field_name = incoming_field_name
|
14
|
+
# if class name not supplied, guess from the field name
|
15
|
+
@class_name = options[:class_name] || name.to_s.singularize.classify
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Tripod::Links
|
3
|
+
# Defines the behaviour for defined links in the resource.
|
4
|
+
class LinkedTo
|
5
|
+
|
6
|
+
# Set readers for the instance variables.
|
7
|
+
attr_accessor :name, :predicate, :options, :multivalued, :field_name, :class_name
|
8
|
+
alias_method :multivalued?, :multivalued
|
9
|
+
|
10
|
+
# Create the new link with a name and optional additional options.
|
11
|
+
def initialize(name, predicate, options = {})
|
12
|
+
@name = name
|
13
|
+
@options = options
|
14
|
+
@predicate = RDF::URI.new(predicate.to_s)
|
15
|
+
@multivalued = options[:multivalued] || false
|
16
|
+
@class_name = options[:class_name] || @name.to_s.classify
|
17
|
+
@field_name = options[:field_name] || (@name.to_s + ( @multivalued ? "_uris" : "_uri" )).to_sym
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/tripod/links.rb
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "tripod/links/linked_to"
|
3
|
+
require "tripod/links/linked_from"
|
4
|
+
|
5
|
+
# This module defines behaviour for fields.
|
6
|
+
module Tripod::Links
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
class_attribute :linked_tos
|
11
|
+
class_attribute :linked_froms
|
12
|
+
self.linked_tos = {}
|
13
|
+
self.linked_froms = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
|
18
|
+
# Define a link to another resource. Creates relevant fields and getter/setter methods. Note that the getter only retrives saved resources from the db.
|
19
|
+
#
|
20
|
+
# @example Define a link away from resources of this class to resources of class Organisation
|
21
|
+
# linked_to :organisation, 'http://example.com/name'
|
22
|
+
#
|
23
|
+
# @example Define a multivalued link away from resources of this class (can be combined with other options)
|
24
|
+
# linked_to :organisations, 'http://example.com/modified_at', multivalued: true
|
25
|
+
#
|
26
|
+
# @example Define a link away from resources of this class, specifying the class and the field name that will be generated
|
27
|
+
# linked_to :org, 'http://example.com/modified_at', class_name: 'Organisation', field: my_field
|
28
|
+
#
|
29
|
+
# @param [ Symbol ] name The name of the link.
|
30
|
+
# @param [ String, RDF::URI ] predicate The predicate for the field.
|
31
|
+
# @param [ Hash ] options The options to pass to the field.
|
32
|
+
#
|
33
|
+
# @option options [ Boolean ] multivalued Is this a multi-valued field? Default is false.
|
34
|
+
# @option options [ String ] class_name The name of the class of resource which we're linking to (normally will derive this from the link name)
|
35
|
+
# @option options [ Symbol ] field_name the symbol of the field that will be generated (normally will just add _uri or _uris to the link name)
|
36
|
+
#
|
37
|
+
# @return [ LinkedTo ] The generated link
|
38
|
+
def linked_to(name, predicate, options = {})
|
39
|
+
add_linked_to(name, predicate, options)
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
# Define that another resource links to this one. Creates a getter with the name you specify.
|
44
|
+
# For this to work, the incoming class needs to define a linked_to relationship.
|
45
|
+
# Just creates the relevant getter which always return an array of objects.
|
46
|
+
#
|
47
|
+
# @example make a method called people which returns Dog objects, via the linked_to :owner field on Dog. We guess the class name based on the linked_from name.
|
48
|
+
# linked_from :dogs, :owner
|
49
|
+
#
|
50
|
+
# @example make a method called doggies which returns Dog objects, via the linked_to :person field on Dog.
|
51
|
+
# linked_from :doggies, :person, class_name: 'Dog'
|
52
|
+
#
|
53
|
+
# @param [ Symbol ] name The name of the link.
|
54
|
+
# @param [ Symbol ] incoming_field_name The name of the linked_to relationship on the other class
|
55
|
+
# @param [ Hash ] options The options to pass to the field.
|
56
|
+
#
|
57
|
+
# @option options [ String ] class_name The name of the class that links to this resource, if we can't guess it from the link name
|
58
|
+
#
|
59
|
+
# @return [ LinkedTo ] The generated link
|
60
|
+
def linked_from(name, incoming_field_name, options = {})
|
61
|
+
add_linked_from(name, incoming_field_name, options)
|
62
|
+
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
|
66
|
+
def add_linked_to(name, predicate, options={})
|
67
|
+
link = linked_to_for(name, predicate, options)
|
68
|
+
linked_tos[name] = link
|
69
|
+
|
70
|
+
# create the field (always is_uri)
|
71
|
+
add_field(link.field_name, predicate, options.merge(is_uri: true))
|
72
|
+
|
73
|
+
create_linked_to_accessors(name, name)
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_linked_from(name, incoming_field_name, options={})
|
77
|
+
link = linked_from_for(name, incoming_field_name, options)
|
78
|
+
linked_froms[name] = link
|
79
|
+
|
80
|
+
create_linked_from_getter(name, name, link)
|
81
|
+
end
|
82
|
+
|
83
|
+
def create_linked_to_accessors(name, meth)
|
84
|
+
link = linked_tos[name]
|
85
|
+
|
86
|
+
create_linked_to_getter(name, meth, link)
|
87
|
+
create_linked_to_setter(name, meth, link)
|
88
|
+
end
|
89
|
+
|
90
|
+
def create_linked_from_getter(name, meth, link)
|
91
|
+
|
92
|
+
generated_methods.module_eval do
|
93
|
+
re_define_method(meth) do
|
94
|
+
klass = Kernel.const_get(link.class_name)
|
95
|
+
|
96
|
+
incoming_link = klass.linked_tos[link.incoming_field_name.to_sym]
|
97
|
+
incoming_predicate = klass.fields[incoming_link.field_name].predicate
|
98
|
+
|
99
|
+
# note - this will only find saved ones.
|
100
|
+
klass
|
101
|
+
.where("?uri <#{incoming_predicate.to_s}> <#{self.uri.to_s}>")
|
102
|
+
.resources
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def create_linked_to_getter(name, meth, link)
|
108
|
+
|
109
|
+
generated_methods.module_eval do
|
110
|
+
re_define_method(meth) do
|
111
|
+
|
112
|
+
klass = Kernel.eval(link.class_name)
|
113
|
+
|
114
|
+
if link.multivalued?
|
115
|
+
|
116
|
+
# # TODO: is there a more efficient way of doing this?
|
117
|
+
|
118
|
+
# note that we can't just do a query like this:
|
119
|
+
# `klass.where('<#{self.uri.to_s}> <#{predicate.to_s}> ?uri').resources`
|
120
|
+
# ... because this will only find saved ones and we want to find resources
|
121
|
+
# whose uris have been set on the resource but not saved to db yet.
|
122
|
+
|
123
|
+
criteria = klass.where('?uri ?p ?o')
|
124
|
+
|
125
|
+
uris = read_attribute(link.field_name)
|
126
|
+
|
127
|
+
filter_str = "FILTER("
|
128
|
+
if uris.any?
|
129
|
+
filter_str += uris.map {|u| "?uri = <#{u.to_s}>" }.join(" || ")
|
130
|
+
else
|
131
|
+
filter_str += "1 = 0"
|
132
|
+
end
|
133
|
+
filter_str += ")"
|
134
|
+
|
135
|
+
criteria.where(filter_str).resources
|
136
|
+
else
|
137
|
+
klass.find(read_attribute(link.field_name)) rescue nil #look it up by it's uri
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def create_linked_to_setter(name, meth, link)
|
145
|
+
|
146
|
+
generated_methods.module_eval do
|
147
|
+
re_define_method("#{meth}=") do |value|
|
148
|
+
|
149
|
+
if link.multivalued?
|
150
|
+
val = value.to_a.map{ |v| v.uri }
|
151
|
+
write_attribute( link.field_name, val)
|
152
|
+
else
|
153
|
+
# set the uri from the passed in resource
|
154
|
+
write_attribute( link.field_name, value.uri )
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# instantiates and returns a new LinkedFrom
|
161
|
+
def linked_from_for(name, incoming_field_name, options)
|
162
|
+
Tripod::Links::LinkedFrom.new(name, incoming_field_name, options)
|
163
|
+
end
|
164
|
+
|
165
|
+
# instantiates and returns a new LinkTo
|
166
|
+
def linked_to_for(name, predicate, options)
|
167
|
+
Tripod::Links::LinkedTo.new(name, predicate, options)
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
data/lib/tripod/version.rb
CHANGED
data/lib/tripod.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
class Dog
|
2
|
+
|
3
|
+
include Tripod::Resource
|
4
|
+
|
5
|
+
rdf_type 'http://example.com/dog'
|
6
|
+
graph_uri 'http://example.com/graph'
|
7
|
+
|
8
|
+
field :name, 'http://example.com/name'
|
9
|
+
|
10
|
+
linked_to :owner, 'http://example.com/owner', class_name: 'Person'
|
11
|
+
linked_to :person, 'http://example.com/person'
|
12
|
+
linked_to :friends, 'http://example.com/friend', multivalued: true, class_name: 'Dog'
|
13
|
+
linked_to :previous_owner, 'http://example.com/prevowner', class_name: 'Person', field_name: :prev_owner_uri
|
14
|
+
|
15
|
+
linked_to :arch_enemy, 'http://example.com/archenemy', class_name: 'Dog'
|
16
|
+
linked_to :enemies, 'http://example.com/enemy', class_name: 'Dog'
|
17
|
+
end
|
data/spec/app/models/person.rb
CHANGED
@@ -12,6 +12,9 @@ class Person
|
|
12
12
|
field :age, 'http://example.com/age', :datatype => RDF::XSD.integer
|
13
13
|
field :important_dates, 'http://example.com/importantdates', :datatype => RDF::XSD.date, :multivalued => true
|
14
14
|
|
15
|
+
linked_from :owns_dogs, :owner, class_name: 'Dog'
|
16
|
+
linked_from :dogs, :person
|
17
|
+
|
15
18
|
before_save :pre_save
|
16
19
|
before_destroy :pre_destroy
|
17
20
|
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Tripod::Links do
|
4
|
+
|
5
|
+
let(:barry) do
|
6
|
+
b = Person.new('http://example.com/id/barry')
|
7
|
+
b.name = 'Barry'
|
8
|
+
b.save!
|
9
|
+
b
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:gary) do
|
13
|
+
g = Person.new('http://example.com/id/gary')
|
14
|
+
g.name = 'Gary'
|
15
|
+
g.save!
|
16
|
+
g
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:jonno) do
|
20
|
+
j = Person.new('http://example.com/id/jonno')
|
21
|
+
j.name = 'Jonno'
|
22
|
+
j.save!
|
23
|
+
j
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:fido) do
|
27
|
+
d = Dog.new('http://example.com/id/fido')
|
28
|
+
d.name = "fido"
|
29
|
+
d.save!
|
30
|
+
d
|
31
|
+
end
|
32
|
+
|
33
|
+
let!(:spot) do
|
34
|
+
d = Dog.new('http://example.com/id/spot')
|
35
|
+
d.name = "spot"
|
36
|
+
d.owner = barry
|
37
|
+
d.save!
|
38
|
+
d
|
39
|
+
end
|
40
|
+
|
41
|
+
let!(:rover) do
|
42
|
+
d = Dog.new('http://example.com/id/rover')
|
43
|
+
d.name = 'Rover'
|
44
|
+
d.owner = barry
|
45
|
+
d.person = gary
|
46
|
+
d.previous_owner = jonno
|
47
|
+
d.save!
|
48
|
+
d
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
describe ".linked_from" do
|
53
|
+
|
54
|
+
context "class name is specified" do
|
55
|
+
it "creates a getter which returns the resources" do
|
56
|
+
barry.owns_dogs.to_a == [rover, spot]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "class name is not specified" do
|
61
|
+
it "creates a getter which returns the resources of the right class, based on the link name" do
|
62
|
+
gary.dogs.to_a.should == [rover]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
describe ".linked_to" do
|
69
|
+
|
70
|
+
it "creates a getter for the field, with a default name, which returns the uri" do
|
71
|
+
rover.owner_uri.should == barry.uri
|
72
|
+
end
|
73
|
+
|
74
|
+
it "creates a setter for the link" do
|
75
|
+
rover.owner = gary
|
76
|
+
rover.owner_uri.should == gary.uri
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'the class name is specified' do
|
80
|
+
it "creates a getter for the link, which returns a resource of the right type" do
|
81
|
+
rover.owner.class.should == Person
|
82
|
+
rover.owner.should == barry
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'the class name is not specified' do
|
87
|
+
it "creates a getter for the link, which automatically returns a resource of the right type (from link name)" do
|
88
|
+
rover.person.class.should == Person
|
89
|
+
rover.person.should == gary
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'when the field name is set to an alternative field name' do
|
94
|
+
it "uses that for the field name" do
|
95
|
+
rover.prev_owner_uri.should == jonno.uri
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'its a multivalued field' do
|
100
|
+
it "creates a getter and setter for multiple values, instantiating the right types of resource" do
|
101
|
+
rover.friends = [fido, spot]
|
102
|
+
|
103
|
+
rover.friends.each do |f|
|
104
|
+
f.class.should == Dog
|
105
|
+
end
|
106
|
+
|
107
|
+
rover.friends.length.should == 2
|
108
|
+
|
109
|
+
rover.friends.to_a.first.uri.should == fido.uri
|
110
|
+
rover.friends.to_a.last.uri.should == spot.uri
|
111
|
+
end
|
112
|
+
|
113
|
+
it "creates field getters and setters with the _uris suffix" do
|
114
|
+
rover.friends_uris = [fido.uri, spot.uri]
|
115
|
+
rover.friends_uris.should == [fido.uri, spot.uri]
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
context "when the value is not set for a link" do
|
121
|
+
context "single valued" do
|
122
|
+
it "should be nil" do
|
123
|
+
rover.arch_enemy.should be_nil
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context "multivalued" do
|
128
|
+
it "should be nil" do
|
129
|
+
rover.enemies.should be_nil
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
data/tripod.gemspec
CHANGED
@@ -19,7 +19,8 @@ Gem::Specification.new do |gem|
|
|
19
19
|
gem.rubyforge_project = "tripod"
|
20
20
|
|
21
21
|
gem.add_dependency "rest-client"
|
22
|
-
gem.add_dependency "activemodel", "
|
22
|
+
gem.add_dependency "activemodel", "~> 3.2"
|
23
|
+
gem.add_dependency "activesupport", "~> 3.2"
|
23
24
|
gem.add_dependency "equivalent-xml"
|
24
25
|
gem.add_dependency "rdf", "~> 1.1"
|
25
26
|
gem.add_dependency "rdf-rdfxml"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tripod
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ric Roberts
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-06-
|
13
|
+
date: 2014-06-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rest-client
|
@@ -30,14 +30,28 @@ dependencies:
|
|
30
30
|
name: activemodel
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
32
32
|
requirements:
|
33
|
-
- - "
|
33
|
+
- - "~>"
|
34
34
|
- !ruby/object:Gem::Version
|
35
35
|
version: '3.2'
|
36
36
|
type: :runtime
|
37
37
|
prerelease: false
|
38
38
|
version_requirements: !ruby/object:Gem::Requirement
|
39
39
|
requirements:
|
40
|
-
- - "
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '3.2'
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: activesupport
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '3.2'
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - "~>"
|
41
55
|
- !ruby/object:Gem::Version
|
42
56
|
version: '3.2'
|
43
57
|
- !ruby/object:Gem::Dependency
|
@@ -207,6 +221,9 @@ files:
|
|
207
221
|
- lib/tripod/fields/standard.rb
|
208
222
|
- lib/tripod/finders.rb
|
209
223
|
- lib/tripod/graphs.rb
|
224
|
+
- lib/tripod/links.rb
|
225
|
+
- lib/tripod/links/linked_from.rb
|
226
|
+
- lib/tripod/links/linked_to.rb
|
210
227
|
- lib/tripod/locale/en.yml
|
211
228
|
- lib/tripod/persistence.rb
|
212
229
|
- lib/tripod/predicates.rb
|
@@ -220,6 +237,7 @@ files:
|
|
220
237
|
- lib/tripod/streaming.rb
|
221
238
|
- lib/tripod/validations/is_url.rb
|
222
239
|
- lib/tripod/version.rb
|
240
|
+
- spec/app/models/dog.rb
|
223
241
|
- spec/app/models/person.rb
|
224
242
|
- spec/app/models/resource.rb
|
225
243
|
- spec/spec_helper.rb
|
@@ -230,6 +248,7 @@ files:
|
|
230
248
|
- spec/tripod/fields_spec.rb
|
231
249
|
- spec/tripod/finders_spec.rb
|
232
250
|
- spec/tripod/graphs_spec.rb
|
251
|
+
- spec/tripod/links_spec.rb
|
233
252
|
- spec/tripod/memcached_cache_store_spec.rb
|
234
253
|
- spec/tripod/persistence_spec.rb
|
235
254
|
- spec/tripod/predicates_spec.rb
|
@@ -266,6 +285,7 @@ signing_key:
|
|
266
285
|
specification_version: 4
|
267
286
|
summary: Active Model style RDF ORM
|
268
287
|
test_files:
|
288
|
+
- spec/app/models/dog.rb
|
269
289
|
- spec/app/models/person.rb
|
270
290
|
- spec/app/models/resource.rb
|
271
291
|
- spec/spec_helper.rb
|
@@ -276,6 +296,7 @@ test_files:
|
|
276
296
|
- spec/tripod/fields_spec.rb
|
277
297
|
- spec/tripod/finders_spec.rb
|
278
298
|
- spec/tripod/graphs_spec.rb
|
299
|
+
- spec/tripod/links_spec.rb
|
279
300
|
- spec/tripod/memcached_cache_store_spec.rb
|
280
301
|
- spec/tripod/persistence_spec.rb
|
281
302
|
- spec/tripod/predicates_spec.rb
|