diff --git a/Gemfile b/Gemfile index 33214ea..1dae4ff 100644 --- a/Gemfile +++ b/Gemfile @@ -1,10 +1,7 @@ source 'https://rubygems.org' +gemspec -# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '4.2.5.1' -# Use sqlite3 as the database for Active Record -gem 'sqlite3' # Use SCSS for stylesheets gem 'sass-rails', '~> 5.0' # Use Uglifier as compressor for JavaScript assets @@ -35,10 +32,6 @@ gem 'sdoc', '~> 0.4.0', group: :doc group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug' - gem 'rspec' - gem 'rspec-rails' - gem 'rspec-its' - gem 'rspec-collection_matchers' end group :development do @@ -51,18 +44,3 @@ end gem 'blacklight', '6.0.1' gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw] - -# RDF/SPARQL -gem 'rdf', '~> 1.99' -gem 'rdf-turtle', '~> 1.99' -gem 'sparql-client', '~> 1.99' -gem 'sparql', '~> 1.99' -gem 'json-ld', '~> 1.99' - -group :development, :test do - #gem 'rdf-do', '~> 1.99' # Using DataObjects for SPARQL store - #gem 'data_objects', '~> 0.10' - #gem 'do_sqlite3' , '~> 0.10' - gem 'rdf-mongo' - gem 'bson_ext' -end diff --git a/Gemfile.lock b/Gemfile.lock index efee228..261b3f3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,43 +1,53 @@ +PATH + remote: . + specs: + sparqlight (0.0.1) + blacklight (~> 6.0) + json-ld (~> 2.0) + rails (~> 4.2) + rdf (~> 2.0) + rdf-turtle (~> 2.0) + sparql-client (~> 2.0) + GEM remote: https://rubygems.org/ specs: - actionmailer (4.2.5.1) - actionpack (= 4.2.5.1) - actionview (= 4.2.5.1) - activejob (= 4.2.5.1) + actionmailer (4.2.8) + actionpack (= 4.2.8) + actionview (= 4.2.8) + activejob (= 4.2.8) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.5.1) - actionview (= 4.2.5.1) - activesupport (= 4.2.5.1) + actionpack (4.2.8) + actionview (= 4.2.8) + activesupport (= 4.2.8) rack (~> 1.6) rack-test (~> 0.6.2) rails-dom-testing (~> 1.0, >= 1.0.5) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (4.2.5.1) - activesupport (= 4.2.5.1) + actionview (4.2.8) + activesupport (= 4.2.8) builder (~> 3.1) erubis (~> 2.7.0) rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - activejob (4.2.5.1) - activesupport (= 4.2.5.1) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (4.2.8) + activesupport (= 4.2.8) globalid (>= 0.3.0) - activemodel (4.2.5.1) - activesupport (= 4.2.5.1) + activemodel (4.2.8) + activesupport (= 4.2.8) builder (~> 3.1) - activerecord (4.2.5.1) - activemodel (= 4.2.5.1) - activesupport (= 4.2.5.1) + activerecord (4.2.8) + activemodel (= 4.2.8) + activesupport (= 4.2.8) arel (~> 6.0) - activesupport (4.2.5.1) + activesupport (4.2.8) i18n (~> 0.7) - json (~> 1.7, >= 1.7.7) minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - arel (6.0.3) - autoprefixer-rails (6.4.0.2) + arel (6.0.4) + autoprefixer-rails (6.7.6) execjs binding_of_caller (0.7.2) debug_inspector (>= 0.0.1) @@ -53,45 +63,54 @@ GEM bootstrap-sass (3.3.7) autoprefixer-rails (>= 5.2.1) sass (>= 3.3.4) - bson (1.12.5) - bson_ext (1.12.5) - bson (~> 1.12.5) - builder (3.2.2) - byebug (9.0.5) + bson (4.2.1) + builder (3.2.3) + byebug (9.0.6) coffee-rails (4.1.1) coffee-script (>= 2.2.0) railties (>= 4.0.0, < 5.1.x) coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.10.0) - concurrent-ruby (1.0.2) + coffee-script-source (1.12.2) + concurrent-ruby (1.0.5) debug_inspector (0.0.2) deprecation (1.0.0) activesupport - diff-lcs (1.2.5) - ebnf (1.0.0) - rdf (~> 1.1) - sxp (~> 0.1, >= 0.1.3) + diff-lcs (1.3) + ebnf (1.1.0) + rdf (~> 2.0) + sxp (~> 1.0) erubis (2.7.0) execjs (2.7.0) globalid (0.3.7) activesupport (>= 4.1.0) - i18n (0.7.0) - jbuilder (2.6.0) - activesupport (>= 3.0.0, < 5.1) + hamster (3.0.0) + concurrent-ruby (~> 1.0) + i18n (0.8.1) + jbuilder (2.6.3) + activesupport (>= 3.0.0, < 5.2) multi_json (~> 1.2) - jquery-rails (4.1.1) + jquery-rails (4.2.2) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - json (1.8.3) - json-ld (1.99.2) - multi_json (~> 1.11) - rdf (~> 1.99) - kaminari (0.17.0) - actionpack (>= 3.0.0) - activesupport (>= 3.0.0) + json (1.8.6) + json-ld (2.1.2) + multi_json (~> 1.12) + rdf (~> 2.1) + kaminari (1.0.1) + activesupport (>= 4.1.0) + kaminari-actionview (= 1.0.1) + kaminari-activerecord (= 1.0.1) + kaminari-core (= 1.0.1) + kaminari-actionview (1.0.1) + actionview + kaminari-core (= 1.0.1) + kaminari-activerecord (1.0.1) + activerecord + kaminari-core (= 1.0.1) + kaminari-core (1.0.1) link_header (0.0.8) loofah (2.0.3) nokogiri (>= 1.5.9) @@ -101,66 +120,68 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) mini_portile2 (2.1.0) - minitest (5.9.0) - mongo (1.12.5) - bson (= 1.12.5) + minitest (5.10.1) + mongo (2.4.1) + bson (>= 4.2.1, < 5.0.0) multi_json (1.12.1) net-http-persistent (2.9.4) - nokogiri (1.6.8) + nokogiri (1.7.0.1) mini_portile2 (~> 2.1.0) - pkg-config (~> 1.1.7) - pkg-config (1.1.7) - rack (1.6.4) + rack (1.6.5) rack-test (0.6.3) rack (>= 1.0) - rails (4.2.5.1) - actionmailer (= 4.2.5.1) - actionpack (= 4.2.5.1) - actionview (= 4.2.5.1) - activejob (= 4.2.5.1) - activemodel (= 4.2.5.1) - activerecord (= 4.2.5.1) - activesupport (= 4.2.5.1) + rails (4.2.8) + actionmailer (= 4.2.8) + actionpack (= 4.2.8) + actionview (= 4.2.8) + activejob (= 4.2.8) + activemodel (= 4.2.8) + activerecord (= 4.2.8) + activesupport (= 4.2.8) bundler (>= 1.3.0, < 2.0) - railties (= 4.2.5.1) + railties (= 4.2.8) sprockets-rails rails-deprecated_sanitizer (1.0.3) activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.7) + rails-dom-testing (1.0.8) activesupport (>= 4.2.0.beta, < 5.0) - nokogiri (~> 1.6.0) + nokogiri (~> 1.6) rails-deprecated_sanitizer (>= 1.0.1) rails-html-sanitizer (1.0.3) loofah (~> 2.0) - railties (4.2.5.1) - actionpack (= 4.2.5.1) - activesupport (= 4.2.5.1) + railties (4.2.8) + actionpack (= 4.2.8) + activesupport (= 4.2.8) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rake (11.2.2) - rdf (1.99.1) + rake (12.0.0) + rdf (2.2.3) + hamster (~> 3.0) link_header (~> 0.0, >= 0.0.8) - rdf-aggregate-repo (1.99.0) - rdf (~> 1.99) - rdf-mongo (1.99.0) - mongo (~> 1.10) - rdf (~> 1.99) - rdf-turtle (1.99.0) - ebnf (~> 1.0) - rdf (~> 1.99) - rdf-xsd (1.99.0) - rdf (~> 1.99) - rdoc (4.2.2) - json (~> 1.4) + rdf-aggregate-repo (2.1.0) + rdf (~> 2.0) + rdf-mongo (2.0.1) + mongo (~> 2.2) + rdf (~> 2.0) + rdf-turtle (2.2.0) + ebnf (~> 1.1) + rdf (~> 2.2) + rdf-xsd (2.1.0) + rdf (~> 2.1) + rdoc (4.3.0) rsolr (1.0.13) builder (>= 2.1.2) rspec (3.5.0) rspec-core (~> 3.5.0) rspec-expectations (~> 3.5.0) rspec-mocks (~> 3.5.0) - rspec-collection_matchers (1.1.2) + rspec-activemodel-mocks (1.0.3) + activemodel (>= 3.0) + activesupport (>= 3.0) + rspec-mocks (>= 2.99, < 4.0) + rspec-collection_matchers (1.1.3) rspec-expectations (>= 2.99.0.beta1) - rspec-core (3.5.2) + rspec-core (3.5.4) rspec-support (~> 3.5.0) rspec-expectations (3.5.0) diff-lcs (>= 1.2.0, < 2.0) @@ -171,7 +192,7 @@ GEM rspec-mocks (3.5.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.5.0) - rspec-rails (3.5.1) + rspec-rails (3.5.2) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) @@ -180,40 +201,42 @@ GEM rspec-mocks (~> 3.5.0) rspec-support (~> 3.5.0) rspec-support (3.5.0) - sass (3.4.22) + sass (3.4.23) sass-rails (5.0.6) railties (>= 4.0.0, < 6) sass (~> 3.1) sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - sdoc (0.4.1) + sdoc (0.4.2) json (~> 1.7, >= 1.7.7) rdoc (~> 4.0) - sparql (1.99.1) + sparql (2.2.0) builder (~> 3.2) - ebnf (~> 1.0) - rdf (~> 1.99) - rdf-aggregate-repo (~> 1.99) - rdf-xsd (~> 1.1) - sparql-client (~> 1.1) - sxp (~> 0.1) - sparql-client (1.99.0) + ebnf (~> 1.1) + rdf (~> 2.1) + rdf-aggregate-repo (~> 2.0) + rdf-xsd (~> 2.1) + sparql-client (~> 2.0) + sxp (~> 1.0) + sparql-client (2.1.0) net-http-persistent (~> 2.9) - rdf (~> 1.1) - spring (1.7.2) - sprockets (3.7.0) + rdf (~> 2.0) + spring (2.0.1) + activesupport (>= 4.2) + sprockets (3.7.1) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.1.1) + sprockets-rails (3.2.0) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) - sqlite3 (1.3.11) - sxp (0.1.5) - thor (0.19.1) - thread_safe (0.3.5) - tilt (2.0.5) + sqlite3 (1.3.13) + sxp (1.0.0) + rdf (~> 2.0) + thor (0.19.4) + thread_safe (0.3.6) + tilt (2.0.6) turbolinks (5.0.1) turbolinks-source (~> 5) turbolinks-source (5.0.0) @@ -223,7 +246,7 @@ GEM railties (>= 3.1) tzinfo (1.2.2) thread_safe (~> 0.1) - uglifier (3.0.1) + uglifier (3.1.6) execjs (>= 0.3.0, < 3) web-console (2.3.0) activemodel (>= 4.0) @@ -236,24 +259,20 @@ PLATFORMS DEPENDENCIES blacklight (= 6.0.1) - bson_ext byebug coffee-rails (~> 4.1.0) jbuilder (~> 2.0) jquery-rails - json-ld (~> 1.99) - rails (= 4.2.5.1) - rdf (~> 1.99) - rdf-mongo - rdf-turtle (~> 1.99) + rdf-mongo (~> 2.0) rspec + rspec-activemodel-mocks rspec-collection_matchers rspec-its rspec-rails sass-rails (~> 5.0) sdoc (~> 0.4.0) - sparql (~> 1.99) - sparql-client (~> 1.99) + sparql (~> 2.0) + sparqlight! spring sqlite3 turbolinks @@ -262,4 +281,4 @@ DEPENDENCIES web-console (~> 2.0) BUNDLED WITH - 1.12.5 + 1.14.4 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a0392f7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ +Copyright 2014 The Board of Trustees of the Leland Stanford Junior University. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/config/application.rb b/config/application.rb index ad5956a..5dcb2f3 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,6 +1,7 @@ require File.expand_path('../boot', __FILE__) require 'rails/all' +require 'blacklight/sparql' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. diff --git a/config/blacklight.yml b/config/blacklight.yml index 3d5102f..ad20a42 100644 --- a/config/blacklight.yml +++ b/config/blacklight.yml @@ -1,15 +1,15 @@ # SPARQL::Client configuration. -# Production references the SPARQL endpoint. Development and test use the local SQLite3 service initialized with test data +# Production references the SPARQL endpoint. Development and test use the local Mongo service initialized with test data development: adapter: Sparql url: <%= ENV['SPARQL_URL'] %> - repository: "mongo" - collection: "nomisma_full" + repository: "mongodb://127.0.0.1:27017/quadb/nomisma_full" test: &test adapter: Sparql - repository: "mongo" - collection: "nomisma" + url: <%= ENV['SPARQL_URL'] %> + repository: "mongodb://127.0.0.1:27017/quadb/nomisma" production: adapter: Sparql url: <%= ENV['SPARQL_URL'] || "http://127.0.0.1/FIXME" %> + repository: "mongodb://127.0.0.1:27017/quadb/nomisma_full" diff --git a/db/seeds.rb b/db/seeds.rb index f55189a..f71c976 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -11,6 +11,7 @@ repo = connection.url if repo.is_a?(RDF::Repository) repo.clear! + require 'rdf/turtle' RDF::Reader.open(Rails.env == "test" ? "db/nomisma.ttl" : "db/nomisma-full.ttl") do |reader| reader.each_statement do |statement| begin diff --git a/app/models/blacklight/sparql.rb b/lib/blacklight/sparql.rb similarity index 88% rename from app/models/blacklight/sparql.rb rename to lib/blacklight/sparql.rb index 43e77af..0e3bdeb 100644 --- a/app/models/blacklight/sparql.rb +++ b/lib/blacklight/sparql.rb @@ -1,3 +1,7 @@ +require 'blacklight/sparql/version' + +## +# SparqLight module Blacklight module Sparql autoload :Document, 'blacklight/sparql/document' diff --git a/app/models/blacklight/sparql/document.rb b/lib/blacklight/sparql/document.rb similarity index 100% rename from app/models/blacklight/sparql/document.rb rename to lib/blacklight/sparql/document.rb diff --git a/app/models/blacklight/sparql/facet_paginator.rb b/lib/blacklight/sparql/facet_paginator.rb similarity index 100% rename from app/models/blacklight/sparql/facet_paginator.rb rename to lib/blacklight/sparql/facet_paginator.rb diff --git a/app/models/blacklight/sparql/repository.rb b/lib/blacklight/sparql/repository.rb similarity index 96% rename from app/models/blacklight/sparql/repository.rb rename to lib/blacklight/sparql/repository.rb index 2abb085..cf45e94 100644 --- a/app/models/blacklight/sparql/repository.rb +++ b/lib/blacklight/sparql/repository.rb @@ -1,5 +1,6 @@ require 'sparql/client' require 'blacklight/sparql' +require 'json/ld' module Blacklight::Sparql class Repository < Blacklight::AbstractRepository @@ -226,17 +227,17 @@ def build_connection SPARQL::Client.new(connection_config[:url]) elsif connection_config[:repository] # Create a new repository to use as client - case repo_config = connection_config[:repository] + case repo_uri = connection_config[:repository] when /sqlite3|postgres/ require 'rdf/do' - require 'do_sqlite3' if repo_config.include?("sqlite3") - require 'do_postgres' if repo_config.include?("postgres") + require 'do_sqlite3' if repo_uri.include?("sqlite3") + require 'do_postgres' if repo_uri.include?("postgres") # Open a local repository and use as a SPARQL client - SPARQL::Client.new RDF::DataObjects::Repository.new(repo_config) + SPARQL::Client.new RDF::DataObjects::Repository.new(uri: repo_uri, logger: false) when /mongo/ require 'rdf/mongo' - SPARQL::Client.new RDF::Mongo::Repository.new(connection_config) + SPARQL::Client.new RDF::Mongo::Repository.new(uri: repo_uri, logger: false) else end else diff --git a/app/models/blacklight/sparql/request.rb b/lib/blacklight/sparql/request.rb similarity index 100% rename from app/models/blacklight/sparql/request.rb rename to lib/blacklight/sparql/request.rb diff --git a/app/models/blacklight/sparql/response.rb b/lib/blacklight/sparql/response.rb similarity index 100% rename from app/models/blacklight/sparql/response.rb rename to lib/blacklight/sparql/response.rb diff --git a/app/models/blacklight/sparql/response/facets.rb b/lib/blacklight/sparql/response/facets.rb similarity index 100% rename from app/models/blacklight/sparql/response/facets.rb rename to lib/blacklight/sparql/response/facets.rb diff --git a/app/models/blacklight/sparql/response/group.rb b/lib/blacklight/sparql/response/group.rb similarity index 100% rename from app/models/blacklight/sparql/response/group.rb rename to lib/blacklight/sparql/response/group.rb diff --git a/app/models/blacklight/sparql/response/pagination_methods.rb b/lib/blacklight/sparql/response/pagination_methods.rb similarity index 100% rename from app/models/blacklight/sparql/response/pagination_methods.rb rename to lib/blacklight/sparql/response/pagination_methods.rb diff --git a/app/models/blacklight/sparql/response/response.rb b/lib/blacklight/sparql/response/response.rb similarity index 100% rename from app/models/blacklight/sparql/response/response.rb rename to lib/blacklight/sparql/response/response.rb diff --git a/app/models/blacklight/sparql/response/spelling.rb b/lib/blacklight/sparql/response/spelling.rb similarity index 100% rename from app/models/blacklight/sparql/response/spelling.rb rename to lib/blacklight/sparql/response/spelling.rb diff --git a/app/models/blacklight/sparql/search_builder_behavior.rb b/lib/blacklight/sparql/search_builder_behavior.rb similarity index 100% rename from app/models/blacklight/sparql/search_builder_behavior.rb rename to lib/blacklight/sparql/search_builder_behavior.rb diff --git a/lib/blacklight/sparql/version.rb b/lib/blacklight/sparql/version.rb new file mode 100644 index 0000000..cd9a770 --- /dev/null +++ b/lib/blacklight/sparql/version.rb @@ -0,0 +1,5 @@ +module Blacklight + module Sparql + VERSION = File.read(File.expand_path("../../../../VERSION", __FILE__)).chomp + end +end diff --git a/lib/generators/blacklight/sparql/assets_generator.rb b/lib/generators/blacklight/sparql/assets_generator.rb new file mode 100644 index 0000000..7587a98 --- /dev/null +++ b/lib/generators/blacklight/sparql/assets_generator.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true +module Blacklight::Sparql + class Assets < Rails::Generators::Base + source_root File.expand_path('../templates', __FILE__) + + def assets + copy_file "blacklight.scss", "app/assets/stylesheets/blacklight.scss" + + return if has_blacklight_assets? + + marker = if turbolinks? + '//= require turbolinks' + else + '//= require jquery_ujs' + end + + insert_into_file "app/assets/javascripts/application.js", :after => marker do +<<-EOF +// +// Required by Blacklight +//= require blacklight/blacklight +EOF + end + + end + + private + + def turbolinks? + @turbolinks ||= IO.read("app/assets/javascripts/application.js").include?('turbolinks') + end + + def has_blacklight_assets? + IO.read("app/assets/javascripts/application.js").include?('blacklight/blacklight') + end + end +end diff --git a/lib/generators/blacklight/sparql/controller_generator.rb b/lib/generators/blacklight/sparql/controller_generator.rb new file mode 100644 index 0000000..2f7277c --- /dev/null +++ b/lib/generators/blacklight/sparql/controller_generator.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true +module Blacklight::Sparql + class ControllerGenerator < Rails::Generators::Base + + source_root File.expand_path('../templates', __FILE__) + + argument :controller_name , type: :string , default: "catalog" + + desc <<-EOS + This generator makes the following changes to your application: + 1. Injects behavior into your user application_controller.rb + 2. Creates a Blacklight::Catalog-based controller + 3. Adds routes for your controller + EOS + + # Add Blacklight to the application controller + def inject_blacklight_controller_behavior + inject_into_class "app/controllers/application_controller.rb", "ApplicationController" do + " # Adds a few additional behaviors into the application controller\n" \ + " include Blacklight::Controller\n" \ + " layout 'blacklight'\n\n" + end + end + + # Generate blacklight catalog controller + def create_blacklight_catalog + template "catalog_controller.rb", "app/controllers/#{controller_name}_controller.rb" + end + + def inject_blacklight_routes + route <<-EOF + concern :searchable, Blacklight::Routes::Searchable.new + + resource :catalog, only: [:index], as: 'catalog', path: '/catalog', controller: 'catalog' do + concerns :searchable + end + EOF + end + end +end diff --git a/lib/generators/blacklight/sparql/document_generator.rb b/lib/generators/blacklight/sparql/document_generator.rb new file mode 100644 index 0000000..8926813 --- /dev/null +++ b/lib/generators/blacklight/sparql/document_generator.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true +require 'rails/generators' + +module Blacklight::Sparql + class DocumentGenerator < Rails::Generators::Base + include Rails::Generators::Migration + + source_root File.expand_path('../templates', __FILE__) + + argument :model_name, :type => :string , :default => "sparql_document" + + desc <<-EOS + This generator makes the following changes to your application: + 1. Creates a blacklight document in your /app/models directory + EOS + + def create_sparql_document + template "sparql_document.rb", "app/models/#{model_name}.rb" + end + + end +end diff --git a/lib/generators/blacklight/sparql/install_generator.rb b/lib/generators/blacklight/sparql/install_generator.rb new file mode 100644 index 0000000..5493889 --- /dev/null +++ b/lib/generators/blacklight/sparql/install_generator.rb @@ -0,0 +1,97 @@ +# frozen_string_literal: true +module Blacklight::Sparql + class Install < Rails::Generators::Base + + source_root File.expand_path('../templates', __FILE__) + + argument :model_name , type: :string , default: "user" + argument :controller_name, type: :string , default: "catalog" + argument :document_name, type: :string , default: "sparql_document" + argument :search_builder_name, type: :string , default: "search_builder" + + class_option :devise , type: :boolean, default: false, aliases: "-d", desc: "Use Devise as authentication logic." + + desc <<-EOS + This generator makes the following changes to your application: + 1. Generates blacklight:models + 2. Creates a number of public assets, including images, stylesheets, and javascript + 3. Injects behavior into your user application_controller.rb + 4. Adds Blacklight routes to your ./config/routes.rb + + Thank you for Installing SparqLight. + EOS + + def bundle_install + Bundler.with_clean_env do + run "bundle install" + end + end + + # Copy all files in templates/public/ directory to public/ + # Call external generator in AssetsGenerator, so we can + # leave that callable seperately too. + # FIXME: Could be blacklight:assets, as there's nothing different here for SPARQL + def copy_public_assets + generate "blacklight:sparql:assets" + end + + def generate_blacklight_sparql_document + generate 'blacklight:sparql:document', document_name + end + + def generate_search_builder + generate 'blacklight:sparql:search_builder', search_builder_name + end + + def generate_blacklight_sparql_models + generate 'blacklight:sparql:models' + end + + # FIXME: Could be blacklight:user, as there's nothing different here for SPARQL + def generate_blacklight_user + + generator_args = [model_name] + if options[:devise] + generator_args << "--devise #{options[:devise]}" + end + + generate 'blacklight:sparql:user', generator_args.join(" ") + end + + # FIXME: Could be blacklight:controller, as there's nothing different here for SPARQL + def generate_controller + generate 'blacklight:sparql:controller', controller_name + end + + def add_default_catalog_route + route("root to: \"#{controller_name}#index\"") + end + + def add_sparqlight_configuration + + insert_into_file "config/application.rb", :after => "require 'rails/all'" do <<-EOF + + require 'blacklight/sparql' +EOF + end + end + + def add_sass_configuration + + insert_into_file "config/application.rb", :after => "config.assets.enabled = true" do < '/'" + end + end +end diff --git a/lib/generators/blacklight/sparql/models_generator.rb b/lib/generators/blacklight/sparql/models_generator.rb new file mode 100644 index 0000000..8540130 --- /dev/null +++ b/lib/generators/blacklight/sparql/models_generator.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true +require 'rails/generators' +require 'rails/generators/migration' + +module Blacklight::Sparql + class ModelsGenerator < Rails::Generators::Base + include Rails::Generators::Migration + + source_root File.expand_path('../templates', __FILE__) + + desc <<-EOS + This generator makes the following changes to your application: + 1. Creates several database migrations if they do not exist in /db/migrate + 2. Creates config/blacklight.yml with a default configuration + EOS + + # Copy all files in templates/config directory to host config + def create_configuration_files + copy_file "config/blacklight.yml", "config/blacklight.yml" + end + + + # Setup the database migrations + def copy_migrations + rake "blacklight:sparql:install:migrations" + end + + def add_routes + route <<-EOF + + concern :exportable, Blacklight::Routes::Exportable.new + + resources :sparql_documents, only: [:show], path: '/catalog', controller: 'catalog' do + concerns :exportable + end + + resources :bookmarks do + concerns :exportable + + collection do + delete 'clear' + end + end + EOF + end + + + end +end diff --git a/lib/generators/blacklight/sparql/search_builder_generator.rb b/lib/generators/blacklight/sparql/search_builder_generator.rb new file mode 100644 index 0000000..3c0d770 --- /dev/null +++ b/lib/generators/blacklight/sparql/search_builder_generator.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true +require 'rails/generators' + +module Blacklight::Sparql + class SearchBuilderGenerator < Rails::Generators::Base + include Rails::Generators::Migration + + source_root File.expand_path('../templates', __FILE__) + + argument :model_name, :type => :string , :default => "search_builder" + + desc <<-EOS + This generator makes the following changes to your application: + 1. Creates a blacklight search builder in your /app/models directory + EOS + def create_search_builder + template "search_builder.rb", "app/models/#{model_name}.rb" + end + + end +end diff --git a/lib/generators/blacklight/sparql/templates/alternate_controller.rb b/lib/generators/blacklight/sparql/templates/alternate_controller.rb new file mode 100644 index 0000000..b2819d6 --- /dev/null +++ b/lib/generators/blacklight/sparql/templates/alternate_controller.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true +class AlternateController < CatalogController + configure_blacklight do |config| + config.index.thumbnail_method = :xyz + end + + def xyz *args + view_context.image_tag "asdfg" + end + + helper_method :xyz + +end diff --git a/lib/generators/blacklight/sparql/templates/blacklight.en.yml b/lib/generators/blacklight/sparql/templates/blacklight.en.yml new file mode 100644 index 0000000..ff834b2 --- /dev/null +++ b/lib/generators/blacklight/sparql/templates/blacklight.en.yml @@ -0,0 +1,3 @@ +en: + blacklight: + application_name: 'Blacklight' \ No newline at end of file diff --git a/lib/generators/blacklight/sparql/templates/blacklight.scss b/lib/generators/blacklight/sparql/templates/blacklight.scss new file mode 100644 index 0000000..3519d90 --- /dev/null +++ b/lib/generators/blacklight/sparql/templates/blacklight.scss @@ -0,0 +1,5 @@ +@import 'bootstrap-sprockets'; + +@import 'bootstrap'; + +@import 'blacklight/blacklight'; diff --git a/lib/generators/blacklight/sparql/templates/catalog_controller.rb b/lib/generators/blacklight/sparql/templates/catalog_controller.rb new file mode 100644 index 0000000..67db553 --- /dev/null +++ b/lib/generators/blacklight/sparql/templates/catalog_controller.rb @@ -0,0 +1,145 @@ +# frozen_string_literal: true +class <%= controller_name.classify %>Controller < ApplicationController + + include Blacklight::Catalog + + configure_blacklight do |config| + # Class for sending and receiving requests from a search index + config.repository_class = Blacklight::Sparql::Repository + + # Class for converting Blacklight's url parameters to into request parameters for the search index + config.search_builder_class = ::SearchBuilder + + # Model that describes a Document + config.document_model = ::SparqlDocument + + # Model that maps search index responses to the blacklight response model + config.response_model = Blacklight::Sparql::Response + + # items to show per page, each number in the array represent another option to choose from. + #config.per_page = [10,20,50,100] + + # Prefix definition for SPARQL queries + config.sparql_prefixes = { + nmo: "http://nomisma.org/ontology#", + skos: "http://www.w3.org/2004/02/skos/core#", + dcterms: "http://purl.org/dc/terms/", + } + + # rdf:type of resources managed by this controller + config.entity_class = "nmo:Denomination" + + # JSON-LD frame used for generating response documents + config.frame = JSON.parse %({ + "@context": { + "nmo": "http://nomisma.org/ontology#", + "skos": "http://www.w3.org/2004/02/skos/core#", + "dcterms": "http://purl.org/dc/terms/", + "skos:prefLabel": {"@language": "en"}, + "skos:definition": {"@language": "en"} + }, + "@type": "nmo:Denomination", + "dcterms:isPartOf": { + "@type": "nmo:FieldOfNumismatics" + } + }) + + + # solr field configuration for search results/index views + config.index.title_field = 'title_display' + config.index.display_type_field = 'format' + + # items to show per page, each number in the array represent another option to choose from. + #config.per_page = [10,20,50,100] + + # Facet fields, may be bound when querying + # * _field name_ is predicate or other distinguishing identifier + # * `label` used for human-readible form label + # * `variable` is the SPARQL variable associated with the field + # * `patterns` (optional) are SPARQL triple patterns necessary to navigate between `?id` and `variable`. Defaults to a pattern composed of `?id`, `predicate` and `variable`. + # * `predicate` defaults to _field name_, but may be set separately if multiple fields use the same predicate (i.e., in different entities) + # * `filter_language` set to true, if the configured language should be used as a filter for the variable result if it is a language-tagged literal. + config.add_facet_field 'num_label', + label: 'Numismatics', + variable: "?num_lab", + patterns: [ + "?id dcterms:isPartOf ?num", + "?num a nmo:FieldOfNumismatics", + "?num skos:prefLabel ?num_lab" + ], + filter_language: true + + # Have BL send all facet field names to Sparql, which has been the default + # previously. Simply remove these lines if you'd rather use Sparql request + # handler defaults, or have no facets. + # Note: this is a generic method, not specific to Solr + config.add_facet_fields_to_solr_request! + config.add_field_configuration_to_solr_request! + + # Sparql fields to be displayed in the index (search results) view + # The ordering of the field names is the order of the display + # * _field name_ is predicate or other distinguishing identifier + # * `variable` is the SPARQL variable associated with the field + # * `predicate` defaults to field name, but may be set separately if multiple fields use the same predicate (i.e., in different entities) + # * `patterns` (optional) are SPARQL triple patterns necessary to navigate between `?id` and `variable`. They default to using the _field name_ as the predicate relating `?id` and `variable`. These are also used in CONSTRUCT when generating RDF triples to frame. + # * `filter_language` set to true, if the configured language should be used as a filter for the variable result if it is a language-tagged literal. + config.add_index_field 'skos:prefLabel', label: 'Label', variable: "?lab", filter_language: true + config.add_index_field 'skos:definition', label: 'Definition', variable: "?defn", filter_language: true + config.add_index_field 'num_label', + field: 'dcterms:isPartOf', + helper_method: 'render_numismatics', + label: 'Numismatics', + variable: "?num_lab", + patterns: [ + "?id dcterms:isPartOf ?num", + "?num a nmo:FieldOfNumismatics", + "?num skos:prefLabel ?num_lab" + ], + filter_language: true + + # Sparql fields to be displayed in the show (single result) view + # The ordering of the field names is the order of the display + config.add_show_field 'skos:prefLabel', label: 'Label', variable: "?lab", filter_language: true + config.add_show_field 'skos:definition', label: 'Definition', variable: "?defn", filter_language: true + config.add_show_field 'num_label', + field: 'dcterms:isPartOf', + helper_method: 'render_numismatics', + label: 'Numismatics', + variable: "?num_lab", + patterns: [ + "?id dcterms:isPartOf ?num", + "?num a nmo:FieldOfNumismatics", + "?num skos:prefLabel ?num_lab" + ], + filter_language: true + + # "fielded" search configuration. Used by pulldown among other places. + # For supported keys in hash, see rdoc for Blacklight::SearchFields + # + # Adds a CONTAINS filter on the specified variable + # * `field name` is predicate or other distinguishing identifier + # * `variable` is one or more SPARQL variables associated with the fields to search + # * `patterns` (optional) are SPARQL triple patterns necessary to filter for matching triples. + # * `predicate` defaults to _field name_, but may be set separately if multiple fields use the same predicate (i.e., in different entities) + # * `patterns` (optional) are SPARQL triple patterns necessary filter results based on the search term. Defaults to `"FILTER(CONTAINS(%{variable}, '%{term}'))"`, there `%{lab_term}` is substituted in the. where multiple variables are CONCATenated + config.add_search_field('all_fields') do |field| + field.label = 'All Fields' + field.default = true + field.variable = %w(?lab ?defn ?num_lab) + field.patterns = ["FILTER(CONTAINS(STR(CONCAT(?lab, ?defn, ?num_lab)), '%{q}'))"] + end + + config.add_search_field('label') do |field| + field.label = 'Label' + field.variable = "?lab" + field.patterns = ["FILTER(CONTAINS(STR(?lab), '%{q}'))"] + end + + # "sort results by" select (pulldown) + # label in pulldown is followed by the name of the SOLR field to sort by and + # whether the sort is ascending or descending (it must be asc or desc + # except in the relevancy case). + config.add_sort_field '?lab asc', label: 'Label' + config.add_sort_field '?defn asc', label: 'Definition' + end +end diff --git a/lib/generators/blacklight/sparql/templates/config/blacklight.yml b/lib/generators/blacklight/sparql/templates/config/blacklight.yml new file mode 100644 index 0000000..ad20a42 --- /dev/null +++ b/lib/generators/blacklight/sparql/templates/config/blacklight.yml @@ -0,0 +1,15 @@ +# SPARQL::Client configuration. +# Production references the SPARQL endpoint. Development and test use the local Mongo service initialized with test data + +development: + adapter: Sparql + url: <%= ENV['SPARQL_URL'] %> + repository: "mongodb://127.0.0.1:27017/quadb/nomisma_full" +test: &test + adapter: Sparql + url: <%= ENV['SPARQL_URL'] %> + repository: "mongodb://127.0.0.1:27017/quadb/nomisma" +production: + adapter: Sparql + url: <%= ENV['SPARQL_URL'] || "http://127.0.0.1/FIXME" %> + repository: "mongodb://127.0.0.1:27017/quadb/nomisma_full" diff --git a/lib/generators/blacklight/sparql/templates/search_builder.rb b/lib/generators/blacklight/sparql/templates/search_builder.rb new file mode 100644 index 0000000..9e9719a --- /dev/null +++ b/lib/generators/blacklight/sparql/templates/search_builder.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true +class SearchBuilder < Blacklight::SearchBuilder + include Blacklight::Sparql::SearchBuilderBehavior +end diff --git a/lib/generators/blacklight/sparql/templates/sparql_document.rb b/lib/generators/blacklight/sparql/templates/sparql_document.rb new file mode 100644 index 0000000..e307062 --- /dev/null +++ b/lib/generators/blacklight/sparql/templates/sparql_document.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true +# +# This class encludes everything necessary for dealing with specific SPARQL _Documents_. +class <%= model_name.classify %> + require_dependency 'blacklight/sparql' + + include Blacklight::Sparql::Document + + self.unique_key = '@id' +end diff --git a/lib/generators/blacklight/sparql/user_generator.rb b/lib/generators/blacklight/sparql/user_generator.rb new file mode 100644 index 0000000..efc9ac5 --- /dev/null +++ b/lib/generators/blacklight/sparql/user_generator.rb @@ -0,0 +1,71 @@ +require 'rails/generators' +require 'rails/generators/migration' + +module Blacklight::Sparql + class UserGenerator < Rails::Generators::Base + include Rails::Generators::Migration + + source_root File.expand_path('../templates', __FILE__) + + argument :model_name, :type => :string , :default => "user" + class_option :devise , :type => :boolean, :default => false, :aliases => "-d", :desc => "Use Devise as authentication logic (this is default)." + + desc <<-EOS + This generator makes the following changes to your application: + 1. Creates a devise-based user model + 2. Injects blacklight-specific behavior into your user model + EOS + # Install Devise? + def generate_devise_assets + if options[:devise] + if ENV['RAILS_VERSION'] =~ /^5\.0/ || ENV['RAILS_VERSION'] == 'edge' + gem 'devise', github: 'plataformatec/devise' # Need > 3.5.3 + else + gem "devise" + end + gem "devise-guests", "~> 0.3" + + Bundler.with_clean_env do + run "bundle install" + end + + generate "devise:install" + generate "devise", model_name.classify + generate "devise_guests", model_name.classify + + # add the #to_s to the model. + insert_into_file("app/models/#{model_name}.rb", before: /end(\n| )*$/) do + "\n # Method added by Blacklight; Blacklight uses #to_s on your\n" \ + " # user class to get a user-displayable login/identifier for\n" \ + " # the account.\n" \ + " def to_s\n" \ + " email\n" \ + " end\n" + end + gsub_file("config/initializers/devise.rb", "config.sign_out_via = :delete", "config.sign_out_via = :get") + end + end + + # Add Blacklight to the user model + def inject_blacklight_user_behavior + file_path = "app/models/#{model_name.underscore}.rb" + if File.exist?(file_path) + inject_into_class file_path, model_name.classify do + "\n if Blacklight::Utils.needs_attr_accessible?" \ + "\n attr_accessible :email, :password, :password_confirmation" \ + "\n end" \ + "\n # Connects this user object to Blacklights Bookmarks." \ + "\n include Blacklight::User\n" + end + else + say_status "warning", <<-EOS.strip_heredocs, :yellow + Blacklight authenticated user functionality not installed, as a user model + could not be found at /app/models/user.rb. If you used a different name, + please re-run the migration and provide that name as an argument. E.g.: + + `rails -g blacklight:user client` + EOS + end + end + end +end diff --git a/sparqlite.gemspec b/sparqlite.gemspec new file mode 100644 index 0000000..977f7a7 --- /dev/null +++ b/sparqlite.gemspec @@ -0,0 +1,33 @@ +# coding: utf-8 +lib = File.expand_path('../lib', __FILE__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +require 'blacklight/sparql/version' + +Gem::Specification.new do |spec| + spec.name = "sparqlight" + spec.version = Blacklight::Sparql::VERSION + spec.authors = ["Gregg Kellogg"] + spec.email = ["gregg@greggkellogg.net"] + spec.summary = %q{SPARQL extension for Blacklight} + spec.homepage = "https://github.com/projectblacklight/sparqlight" + spec.license = "Apache 2.0" + + spec.files = %w(Rakefile README.md LICENSE VERSION) + Dir['{app,lib}/**/*'] + spec.require_paths = ["lib"] + + spec.add_dependency "rails", '~> 4.2' + spec.add_dependency 'blacklight', '~> 6.0' + spec.add_dependency 'json-ld', '~> 2.0' + spec.add_dependency 'rdf', '~> 2.0' + spec.add_dependency "rdf-turtle", '~> 2.0' + spec.add_dependency 'sparql-client', '~> 2.0' + + spec.add_development_dependency "sparql", '~> 2.0' + spec.add_development_dependency 'rdf-mongo', '~> 2.0' + spec.add_development_dependency 'sqlite3' + spec.add_development_dependency 'rspec' + spec.add_development_dependency 'rspec-rails' + spec.add_development_dependency 'rspec-its' + spec.add_development_dependency 'rspec-activemodel-mocks' + spec.add_development_dependency 'rspec-collection_matchers' + end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 62faa50..fff09d0 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -22,7 +22,10 @@ ENV['RAILS_ENV'] = 'test' require 'blacklight' +require 'blacklight/sparql' require 'rspec/its' +require 'rspec/collection_matchers' + RSpec.configure do |config| # rspec-expectations config goes here. You can use an alternate # assertion/expectation library such as wrong or the stdlib/minitest