diff --git a/README.md b/README.md index 9544881..4a6e2cd 100644 --- a/README.md +++ b/README.md @@ -18,44 +18,50 @@ ActiveModel-style Ruby ORM for RDF Linked Data. Works with SPARQL 1.1 HTTP endpo 2. Configure it (in application.rb, or development.rb/production.rb/test.rb) - # (values shown are the defaults) - Tripod.configure do |config| - config.update_endpoint = 'http://127.0.0.1:3030/tripod/update' - config.query_endpoint = 'http://127.0.0.1:3030/tripod/sparql' - config.timeout_seconds = 30 - end +```rb +# (values shown are the defaults) +Tripod.configure do |config| + config.update_endpoint = 'http://127.0.0.1:3030/tripod/update' + config.query_endpoint = 'http://127.0.0.1:3030/tripod/sparql' + config.timeout_seconds = 30 +end +``` 3. Include it in your model classes. - class Person - include Tripod::Resource +```rb +class Person + include Tripod::Resource - # these are the default rdf-type and graph for resources of this class - rdf_type 'http://example.com/person' - graph_uri 'http://example.com/people' + # these are the default rdf-type and graph for resources of this class + rdf_type 'http://example.com/person' + graph_uri 'http://example.com/people' - field :name, 'http://example.com/name' - field :knows, 'http://example.com/knows', :multivalued => true, :is_uri => true - field :aliases, 'http://example.com/alias', :multivalued => true - field :age, 'http://example.com/age', :datatype => RDF::XSD.integer - field :important_dates, 'http://example.com/importantdates', :datatype => RDF::XSD.date, :multivalued => true - end + field :name, 'http://example.com/name' + field :knows, 'http://example.com/knows', :multivalued => true, :is_uri => true + field :aliases, 'http://example.com/alias', :multivalued => true + field :age, 'http://example.com/age', :datatype => RDF::XSD.integer + field :important_dates, 'http://example.com/importantdates', :datatype => RDF::XSD.date, :multivalued => true +end - # Note: Active Model validations are supported +# Note: Active Model validations are supported +``` 4. Use it - uri = 'http://example.com/ric' - p = Person.new(uri) - p.name = 'Ric' - p.age = 31 - p.aliases = ['Rich', 'Richard'] - p.important_dates = [Date.new(2011,1,1)] - p.save! +```rb +uri = 'http://example.com/ric' +p = Person.new(uri) +p.name = 'Ric' +p.age = 31 +p.aliases = ['Rich', 'Richard'] +p.important_dates = [Date.new(2011,1,1)] +p.save! - people = Person.all.resources #=> returns all people as an array +people = Person.all.resources #=> returns all people as an array - ric = Person.find('http://example.com/ric') #=> returns a single Person object. +ric = Person.find('http://example.com/ric') #=> returns a single Person object. +``` ## Note: @@ -64,73 +70,83 @@ Tripod doesn't supply a database. You need to install one. I recommend [Fuseki]( ## Some Other interesting features -## Eager Loading +### Eager Loading - asa = Person.find('http://example.com/asa') - ric = Person.find('http://example.com/ric') - ric.knows = asa.uri +```rb +asa = Person.find('http://example.com/asa') +ric = Person.find('http://example.com/ric') +ric.knows = asa.uri - ric.eager_load_predicate_triples! #does a big DESCRIBE statement behind the scenes - knows = ric.get_related_resource('http://example.com/knows', Resource) - knows.label # this won't cause another database lookup +ric.eager_load_predicate_triples! #does a big DESCRIBE statement behind the scenes +knows = ric.get_related_resource('http://example.com/knows', Resource) +knows.label # this won't cause another database lookup - ric.eager_load_object_triples! #does a big DESCRIBE statement behind the scenes - asa = ric.get_related_resource('http://example.com/asa', Person) # returns a fully hydrated Person object for asa, without an extra lookup +ric.eager_load_object_triples! #does a big DESCRIBE statement behind the scenes +asa = ric.get_related_resource('http://example.com/asa', Person) # returns a fully hydrated Person object for asa, without an extra lookup +``` -## Defining a graph at instantiation-time +## Defining a graph at instantiation-time - class Resource - include Tripod::Resource - field :label, RDF::RDFS.label +```rb +class Resource + include Tripod::Resource + field :label, RDF::RDFS.label - # notice also that you don't need to supply an rdf type or graph here! - end + # notice also that you don't need to supply an rdf type or graph here! +end - r = Resource.new('http://example.com/foo', 'http://example.com/mygraph') - r.label = "example" - r.save +r = Resource.new('http://example.com/foo', 'http://example.com/mygraph') +r.label = "example" +r.save - # Note: Tripod assumes you want to store all resources in named graphs. - # So if you don't supply a graph at any point (i.e. class or instance level), - # you will get an error when you try to persist the resource. +# Note: Tripod assumes you want to store all resources in named graphs. +# So if you don't supply a graph at any point (i.e. class or instance level), +# you will get an error when you try to persist the resource. +``` ## Reading and writing arbitrary predicates - r.write_predicate(RDF.type, 'http://example.com/myresource/type') - r.read_predicate(RDF.type) #=> [RDF::URI.new("http://example.com/myresource/type")] +```rb +r.write_predicate(RDF.type, 'http://example.com/myresource/type') +r.read_predicate(RDF.type) #=> [RDF::URI.new("http://example.com/myresource/type")] +``` ## Finders and criteria - # A Tripod::Criteria object defines a set of constraints for a SPARQL query. - # It doesn't actually do anything against the DB until you run resources, first, or count on it. - # (from Tripod::CriteriaExecution) +```rb +# A Tripod::Criteria object defines a set of constraints for a SPARQL query. +# It doesn't actually do anything against the DB until you run resources, first, or count on it. +# (from Tripod::CriteriaExecution) - Person.all #=> returns a Tripod::Criteria object which selects all resources of rdf_type http://example.com/person, in the http://example.com/people graph +Person.all #=> returns a Tripod::Criteria object which selects all resources of rdf_type http://example.com/person, in the http://example.com/people graph - Resource.all #=> returns a criteria object to return resources in the database (as no rdf_type or graph_uri specified at class level) +Resource.all #=> returns a criteria object to return resources in the database (as no rdf_type or graph_uri specified at class level) - Person.all.resources #=> returns all the actual resources for the criteria object, as an array-like object +Person.all.resources #=> returns all the actual resources for the criteria object, as an array-like object - Person.all.resources(:return_graph => false) #=> returns the actual resources, but without returning the graph_uri in the select (helps avoid pagination issues). Note: doesn't set the graph uri on the instantiated resources. +Person.all.resources(:return_graph => false) #=> returns the actual resources, but without returning the graph_uri in the select (helps avoid pagination issues). Note: doesn't set the graph uri on the instantiated resources. - Person.first #=> returns the first person (by crafting a sparql query under the covers that only returns 1 result) +Person.first #=> returns the first person (by crafting a sparql query under the covers that only returns 1 result) - Person.first(:return_graph => false) # as with resources, doesn't return / set the graph_uri. +Person.first(:return_graph => false) # as with resources, doesn't return / set the graph_uri. - Person.count #=> returns the count of all people (by crafting a count query under the covers that only returns a count) +Person.count #=> returns the count of all people (by crafting a count query under the covers that only returns a count) - # note that you need to use ?uri as the variable for the subject. - Person.where("?uri 'Joe'") #=> returns a Tripod::Criteria object +# note that you need to use ?uri as the variable for the subject. +Person.where("?uri 'Joe'") #=> returns a Tripod::Criteria object - Resource.graph("http://example.com/mygraph") #=> Retruns a criteria object with a graph restriction (note: if graph_uri set on the class, it will default to using this) +Resource.graph("http://example.com/mygraph") #=> Retruns a criteria object with a graph restriction (note: if graph_uri set on the class, it will default to using this) - Resource.find_by_sparql('SELECT ?uri ?graph WHERE { GRAPH ?graph { ?uri ?p ?o } }') #=> allows arbitrary sparql. Again, use ?uri for the variable of the subjects (and ?graph for the graph). +Resource.find_by_sparql('SELECT ?uri ?graph WHERE { GRAPH ?graph { ?uri ?p ?o } }') #=> allows arbitrary sparql. Again, use ?uri for the variable of the subjects (and ?graph for the graph). +``` ## Chainable criteria - Person.all.where("?uri 'Ric'").where("?uri ).first +```rb +Person.all.where("?uri 'Ric'").where("?uri ).first - Person.where("?uri ?name").limit(1).offset(0).order("DESC(?name)") +Person.where("?uri ?name").limit(1).offset(0).order("DESC(?name)") +``` ## Running tests @@ -140,4 +156,4 @@ Some tests require memcached to be set up and running. The tests that require me [Full Documentation](http://rubydoc.info/gems/tripod/frames) -Copyright (c) 2012 [Swirrl IT Limited](http://swirrl.com). Released under MIT License \ No newline at end of file +Copyright (c) 2012 [Swirrl IT Limited](http://swirrl.com). Released under MIT License