Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial commit

  • Loading branch information...
commit 78ec944db7887aa424f01aea5b2fcabfec39773f 0 parents
@bhuga bhuga authored
27 README.md
@@ -0,0 +1,27 @@
+# Spira
+
+Bringing linked data to life
+
+Spira is a framework for using the information in RDF.rb repositories as model objects.
+
+Example:
+
+ class Person
+ base_path "http://example.org/example/people"
+ source ::RDF::Repository
+
+ property :name, RDF::FOAF.name, String
+ property :age, RDF::FOAF.age, Integer
+
+ end
+
+ bob = Person.create 'bob'
+ bob.age = 15
+ bob.name = "Bob Smith"
+ bob.save!
+
+ bob.each_statement
+ #<http://example.org/example/people/bob> <http://xmlns.com/foaf/0.1/age> "15"^^<http://www.w3.org/2001/XMLSchema#integer> .
+ #<http://example.org/example/people/bob> <http://www.w3.org/2000/01/rdf-schema#label> "Bob Smith" .
+
+You probably don't want to be using this yet. Major changes are still forthcoming.
24 UNLICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <http://unlicense.org/>
97 lib/spira.rb
@@ -0,0 +1,97 @@
+require 'rdf'
+require 'rdf/isomorphic'
+
+module RDF
+ module Enumerable
+ alias_method :==, :isomorphic_with?
+ end
+end
+
+
+module Spira
+
+ def self.included(child)
+ child.extend ClassMethods
+ child.instance_eval do
+ class << self
+ attr_accessor :base_uri, :repository, :properties
+ end
+ @properties = {}
+ end
+ end
+
+ attr_reader :uri
+
+ def initialize(identifier, attributes = {})
+ @uri = RDF::URI.parse(self.class.base_uri + "/" + identifier)
+ @repo = RDF::Repository.new
+ @repo.insert(*(attributes[:statements])) unless attributes[:statements].nil?
+ @original_repo = @repo.dup
+ end
+
+ def destroy!
+ self.class.properties.each do | name, predicate |
+ result = (self.class.repository.query(:subject => @uri, :predicate => predicate))
+ self.class.repository.delete(*result) unless result.empty?
+ end
+ end
+
+ def save!
+ destroy!
+ self.class.repository.insert(*@repo)
+ end
+
+ def each(*args, &block)
+ @repo.each(*args, &block)
+ end
+ include ::RDF::Enumerable, ::RDF::Queryable
+
+ module ClassMethods
+
+ def source(klass, *args)
+ self.repository = klass.new *args
+ end
+
+ def base_path(string)
+ self.base_uri = string
+ end
+
+ def property(name, predicate, type)
+ @properties[name] = predicate
+ name_equals = (name.to_s + "=").to_sym
+ self.class_eval do
+
+ define_method(name_equals) do |arg|
+ old = @repo.query(:subject => @uri, :predicate => predicate)
+ @repo.delete(old) unless old.empty?
+ @repo.insert(RDF::Statement.new(@uri, predicate, arg))
+ end
+
+ define_method(name) do
+ object = @repo.query(:subject => @uri, :predicate => predicate).first.object
+ object = case
+ when type == String
+ object.object.to_s
+ when type == Integer
+ object.object
+ end
+ end
+
+ end
+ end
+
+ def find(identifier)
+ statements = self.repository.query(:subject => RDF::URI.parse(self.base_uri + "/" + identifier))
+ if statements.empty?
+ nil
+ else
+ self.new(identifier, :statements => statements)
+ end
+ end
+
+ def create(name, attributes = {})
+ self.new(name, attributes)
+ end
+
+ end
+end
3  spec/fixtures/bob.nt
@@ -0,0 +1,3 @@
+<http://example.org/example/people/bob> <http://xmlns.com/foaf/0.1/age> "15"^^<http://www.w3.org/2001/XMLSchema#integer> .
+<http://example.org/example/people/bob> <http://www.w3.org/2000/01/rdf-schema#label> "Bob Smith" .
+
18 spec/fixtures/person.rb
@@ -0,0 +1,18 @@
+require 'spira'
+require 'rdf'
+
+class Person
+
+ include Spira
+
+ # Find and create instances here
+ source ::RDF::Repository
+
+ # the base path to find Persons
+ base_path "http://example.org/example/people"
+
+ property :name, RDF::RDFS.label, String
+ property :age, RDF::FOAF.age, Integer
+
+
+end
161 spec/spira.spec
@@ -0,0 +1,161 @@
+$:.unshift(File.join(File.dirname(__FILE__),'..','lib'))
+$:.unshift(File.join(File.dirname(__FILE__),'fixtures',''))
+
+$:.unshift(File.join(File.dirname(__FILE__),'..','..','rdf-spec','lib'))
+$:.unshift(File.join(File.dirname(__FILE__),'..','..','rdf','lib'))
+require 'spira'
+require 'rdf/spec/enumerable'
+require 'rdf/spec'
+
+def fixture(filename)
+ File.join(File.dirname(__FILE__),'fixtures',filename)
+end
+
+describe Spira do
+
+ context "The person fixture" do
+
+ before :all do
+ require 'person'
+ require 'rdf/ntriples'
+ @person_repository = RDF::Repository.load(fixture('bob.nt'))
+ end
+
+ it "should be instantiable" do
+ x = Person.create 'bob'
+ end
+
+ it "should know its source" do
+ Person.repository.should be_a RDF::Repository
+ end
+
+ it "should have a base path" do
+ Person.base_uri.should == "http://example.org/example/people"
+ end
+
+ it "should have a find method" do
+ Person.should respond_to :find
+ end
+
+ it "should return nil for a non-existent person" do
+ Person.find('nobody').should == nil
+ end
+
+ context "A newly-created person" do
+
+ before :each do
+ @person = Person.create 'bob'
+ end
+
+ after :each do
+ @person.destroy!
+ end
+
+ it "should be destroyable" do
+ lambda {@person.destroy!}.should_not raise_error
+ end
+
+ it "should be createable with a URI path" do
+ @person.uri.should be_a RDF::URI
+ @person.uri.to_s.should == "http://example.org/example/people/bob"
+ end
+
+ it "should have a name method" do
+ @person.should respond_to :name
+ end
+
+ it "should have an age method" do
+ @person.should respond_to :age
+ end
+
+ it "should allow setting a name" do
+ lambda { @person.name = "Bob Smith" }.should_not raise_error
+ end
+
+ it "should allow getting a name" do
+ @person.name = "Bob Smith"
+ @person.name.should == "Bob Smith"
+ end
+
+ it "should allow setting an age" do
+ lambda { @person.age = 15 }.should_not raise_error
+ end
+
+ it "should allow getting an age" do
+ @person.age = 15
+ @person.age.should == 15
+ end
+
+ it "should return strings for the name" do
+ @person.name = "Bob Smith"
+ @person.name.should be_a String
+ end
+
+ it "should return integers for the age" do
+ @person.age = 15
+ @person.age.should be_a Integer
+ end
+
+ it "should save both properties" do
+ @person.age = 15
+ @person.name = "Bob Smith"
+ @person.age.should == 15
+ @person.name.should == "Bob Smith"
+ end
+
+ end
+
+ context "getting, setting, and saving" do
+
+ before :all do
+ require 'rdf/ntriples'
+ @person_repository = RDF::Repository.load(fixture('bob.nt'))
+ end
+
+ before :each do
+ @person = Person.create 'bob'
+ @person.name = "Bob Smith"
+ @person.age = 15
+ end
+
+ after :each do
+ @person.destroy!
+ end
+
+ it "should be saveable" do
+ lambda { @person.save! }.should_not raise_error
+ end
+
+ it "should be findable after saving" do
+ @person.save!
+ bob = Person.find 'bob'
+ bob.should == @person
+ end
+
+ it "should not find non-existent identifiers after saving one" do
+ @person.save!
+ Person.find('xyz').should == nil
+ end
+
+ end
+
+ context "as an RDF::Enumerable" do
+
+ before :each do
+ @statements = @person_repository
+ @person = Person.create 'bob'
+ @person.name = "Bob Smith"
+ @person.age = 15
+ @enumerable = @person
+ end
+
+ it_should_behave_like RDF_Enumerable
+ end
+
+ end
+
+
+end
+
+
+
Please sign in to comment.
Something went wrong with that request. Please try again.