publish_my_data 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +37 -0
  3. data/Rakefile +41 -0
  4. data/app/assets/javascripts/publish_my_data/application.js +15 -0
  5. data/app/assets/javascripts/publish_my_data/resources.js +2 -0
  6. data/app/assets/stylesheets/publish_my_data/application.css +13 -0
  7. data/app/assets/stylesheets/publish_my_data/resources.css +4 -0
  8. data/app/controllers/publish_my_data/application_controller.rb +49 -0
  9. data/app/controllers/publish_my_data/datasets_controller.rb +48 -0
  10. data/app/controllers/publish_my_data/errors_controller.rb +9 -0
  11. data/app/controllers/publish_my_data/home_controller.rb +4 -0
  12. data/app/controllers/publish_my_data/resources_controller.rb +103 -0
  13. data/app/controllers/publish_my_data/sparql_controller.rb +50 -0
  14. data/app/helpers/publish_my_data/application_helper.rb +4 -0
  15. data/app/helpers/publish_my_data/resources_helper.rb +28 -0
  16. data/app/helpers/publish_my_data/sparql_helper.rb +7 -0
  17. data/app/models/publish_my_data/concept_scheme.rb +5 -0
  18. data/app/models/publish_my_data/dataset.rb +61 -0
  19. data/app/models/publish_my_data/ontology.rb +5 -0
  20. data/app/models/publish_my_data/rdf_type.rb +6 -0
  21. data/app/models/publish_my_data/resource.rb +21 -0
  22. data/app/views/layouts/publish_my_data/application.html.erb +14 -0
  23. data/app/views/layouts/publish_my_data/error.html.erb +3 -0
  24. data/app/views/publish_my_data/datasets/index.html.erb +20 -0
  25. data/app/views/publish_my_data/datasets/show.html.erb +18 -0
  26. data/app/views/publish_my_data/datasets/themes.html.erb +3 -0
  27. data/app/views/publish_my_data/errors/not_found.html.erb +1 -0
  28. data/app/views/publish_my_data/resources/_predicates_table.html.erb +22 -0
  29. data/app/views/publish_my_data/resources/_predicates_table_head.html.erb +6 -0
  30. data/app/views/publish_my_data/resources/_resource_formats.html.erb +11 -0
  31. data/app/views/publish_my_data/resources/_uri_and_label.html.erb +3 -0
  32. data/app/views/publish_my_data/resources/index.html.erb +39 -0
  33. data/app/views/publish_my_data/resources/show.html.erb +3 -0
  34. data/app/views/publish_my_data/sparql/_ask_formats.html.erb +3 -0
  35. data/app/views/publish_my_data/sparql/_construct_formats.html.erb +3 -0
  36. data/app/views/publish_my_data/sparql/_describe_formats.html.erb +1 -0
  37. data/app/views/publish_my_data/sparql/_error_message.html.erb +3 -0
  38. data/app/views/publish_my_data/sparql/_form.html.erb +4 -0
  39. data/app/views/publish_my_data/sparql/_formats.html.erb +6 -0
  40. data/app/views/publish_my_data/sparql/_pagination.html.erb +6 -0
  41. data/app/views/publish_my_data/sparql/_results.html.erb +5 -0
  42. data/app/views/publish_my_data/sparql/_results_data.html.erb +4 -0
  43. data/app/views/publish_my_data/sparql/_select_formats.html.erb +3 -0
  44. data/app/views/publish_my_data/sparql/endpoint.html.erb +10 -0
  45. data/config/initializers/tripod.rb +5 -0
  46. data/config/initializers/vocabularies.rb +1 -0
  47. data/config/routes.rb +33 -0
  48. data/lib/publish_my_data.rb +43 -0
  49. data/lib/publish_my_data/engine.rb +9 -0
  50. data/lib/publish_my_data/renderers.rb +44 -0
  51. data/lib/publish_my_data/sparql_query.rb +117 -0
  52. data/lib/publish_my_data/sparql_query_result.rb +49 -0
  53. data/lib/publish_my_data/version.rb +3 -0
  54. data/lib/tasks/publish_my_data_tasks.rake +4 -0
  55. data/spec/controllers/publish_my_data/datasets_controller_spec.rb +190 -0
  56. data/spec/controllers/publish_my_data/resources_controller_spec.rb +399 -0
  57. data/spec/controllers/publish_my_data/sparql_controller_spec.rb +172 -0
  58. data/spec/dummy/README.rdoc +261 -0
  59. data/spec/dummy/Rakefile +7 -0
  60. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  61. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  62. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  63. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  64. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  65. data/spec/dummy/config.ru +4 -0
  66. data/spec/dummy/config/application.rb +68 -0
  67. data/spec/dummy/config/boot.rb +10 -0
  68. data/spec/dummy/config/environment.rb +5 -0
  69. data/spec/dummy/config/environments/development.rb +38 -0
  70. data/spec/dummy/config/environments/production.rb +65 -0
  71. data/spec/dummy/config/environments/test.rb +41 -0
  72. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  73. data/spec/dummy/config/initializers/inflections.rb +15 -0
  74. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  75. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  76. data/spec/dummy/config/initializers/session_store.rb +8 -0
  77. data/spec/dummy/config/initializers/wrap_parameters.rb +10 -0
  78. data/spec/dummy/config/locales/en.yml +5 -0
  79. data/spec/dummy/config/routes.rb +4 -0
  80. data/spec/dummy/log/development.log +211 -0
  81. data/spec/dummy/log/test.log +105012 -0
  82. data/spec/dummy/public/404.html +26 -0
  83. data/spec/dummy/public/422.html +26 -0
  84. data/spec/dummy/public/500.html +25 -0
  85. data/spec/dummy/public/favicon.ico +0 -0
  86. data/spec/dummy/script/rails +6 -0
  87. data/spec/factories/dataset_factories.rb +12 -0
  88. data/spec/factories/property_factories.rb +13 -0
  89. data/spec/factories/resource_factories.rb +37 -0
  90. data/spec/features/running_a_sparql_query_spec.rb +324 -0
  91. data/spec/features/uri_dereferencing_flow_spec.rb +61 -0
  92. data/spec/features/uri_dereferencing_spec.rb +89 -0
  93. data/spec/features/viewing_a_def_spec.rb +45 -0
  94. data/spec/features/viewing_a_doc_spec.rb +124 -0
  95. data/spec/features/viewing_resource_not_in_our_domain_spec.rb +31 -0
  96. data/spec/lib/publish_my_data/sparql_query_spec.rb +495 -0
  97. data/spec/models/publish_my_data/dataset_spec.rb +29 -0
  98. data/spec/models/publish_my_data/resource_spec.rb +23 -0
  99. data/spec/renderers/publish_my_data/renderers_spec.rb +79 -0
  100. data/spec/spec_helper.rb +53 -0
  101. metadata +242 -0
@@ -0,0 +1,9 @@
1
+ module PublishMyData
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace PublishMyData
4
+
5
+ config.generators do |g|
6
+ g.test_framework :rspec
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,44 @@
1
+ require "action_controller"
2
+
3
+ # turtle
4
+ Mime::Type.register("text/turtle", :ttl)
5
+ ActionController::Renderers.add :ttl do |obj, opts|
6
+ str = obj.respond_to?(:to_ttl) ? obj.to_ttl : obj.to_s
7
+ send_data str, :type => Mime::TTL, :disposition => "inline"
8
+ end
9
+
10
+ #rdf
11
+ Mime::Type.register("application/rdf+xml", :rdf)
12
+ ActionController::Renderers.add :rdf do |obj, opts|
13
+ str = obj.respond_to?(:to_rdf) ? obj.to_rdf : obj.to_s
14
+ send_data str, :type => Mime::RDF, :disposition => "inline"
15
+ end
16
+
17
+ #ntriples
18
+ # Note: We've elected not to respond with ntriples to text/plain as it confuses things
19
+ # (text/plain is used for plain-text tabular sparql-select results!
20
+ Mime::Type.register("application/n-triples", :nt )
21
+
22
+ ActionController::Renderers.add :nt do |obj, opts|
23
+ str = obj.respond_to?(:to_nt) ? obj.to_nt : obj.to_s
24
+ send_data str, :type => Mime::NT, :disposition => "inline"
25
+ end
26
+
27
+ # re-register JSON with extra headers
28
+ Mime::Type.unregister(:json)
29
+ Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest application/sparql-results+json )
30
+ # json already has a renderer
31
+
32
+ # likewise for XML
33
+ Mime::Type.unregister(:xml)
34
+ Mime::Type.register "application/xml", :xml, %w( text/xml application/x-xml application/sparql-results+xml )
35
+ # xml already has a renderer
36
+
37
+ # text mime type and renderer already defined
38
+
39
+ # csv mime type already registered.
40
+ # csv (for sparql SELECT results)
41
+ ActionController::Renderers.add :csv do |obj, opts|
42
+ str = obj.respond_to?(:to_csv) ? obj.to_csv : obj.to_s
43
+ send_data str, :type => Mime::CSV, :disposition => "inline"
44
+ end
@@ -0,0 +1,117 @@
1
+ module PublishMyData
2
+
3
+ class SparqlQueryExecutionException < StandardError; end
4
+
5
+ class SparqlQuery < Tripod::SparqlQuery
6
+
7
+ attr_reader :request_format # symbol representing the format of the original request
8
+ attr_reader :parent_query # set if this query originated from another (e.g. pagination or count)
9
+
10
+ def initialize(query_string, request_format_symbol = :html, parent_query = nil)
11
+ super(query_string)
12
+ @parent_query = parent_query
13
+ @request_format = request_format_symbol
14
+ end
15
+
16
+ # executes the query, using the right format parameters (for fuseki) for the query type and request format
17
+ def execute
18
+ begin
19
+ case query_type
20
+ when :select
21
+ result_str = Tripod::SparqlClient::Query.select(self.query, select_format_str)
22
+ when :ask
23
+ result_str = Tripod::SparqlClient::Query.ask(self.query, ask_format_str)
24
+ when :construct
25
+ result_str = Tripod::SparqlClient::Query.construct(self.query, construct_or_describe_header)
26
+ when :describe
27
+ result_str = Tripod::SparqlClient::Query.describe(self.query, construct_or_describe_header)
28
+ else
29
+ raise SparqlQueryExecutionException.new("Unsupported Query Type. Please enter only SELECT, CONSTRUCT, DESCRIBE or ASK queries.")
30
+ end
31
+
32
+ rescue Tripod::Errors::BadSparqlRequest => bad_sparql
33
+ if self.parent_query
34
+ # call execute on the parent(this will fail too), but it means that we get the right error for
35
+ # the user-entered query
36
+ parent_query.execute
37
+ else
38
+ raise SparqlQueryExecutionException.new(process_sparql_parse_failed_exception_message(bad_sparql))
39
+ end
40
+ end
41
+
42
+ PublishMyData::SparqlQueryResult.new(result_str)
43
+ end
44
+
45
+ # make a pagination version and execute that.
46
+ def paginate(page, per_page, look_ahead=0)
47
+ self.as_pagination_query(page, per_page, look_ahead).execute
48
+ end
49
+
50
+ # return the number of results that this query returns
51
+ # (creates and executes a count query behind the scenes)
52
+ def count
53
+ result = JSON.parse(self.as_count_query.execute.to_s)["results"]["bindings"]
54
+ result[0][".1"]["value"].to_i
55
+ end
56
+
57
+ def allow_pagination?
58
+ self.query_type == :select
59
+ end
60
+
61
+ def as_count_query(format = :json)
62
+ # return the paginated version
63
+ PublishMyData::SparqlQuery.new(as_count_query_str, format, self) # pass in the original query
64
+ end
65
+
66
+ # for selects only, turn this into a paginated version. Returns a whole new SparqlQuery object.
67
+ def as_pagination_query(page, per_page, look_ahead=0)
68
+
69
+ check_subqueryable!
70
+
71
+ limit = per_page + look_ahead
72
+ offset = per_page * (page-1)
73
+ # wrap it in a subselect with limit and offset
74
+ paginated_query = "SELECT * { #{self.body} } LIMIT #{limit} OFFSET #{offset}"
75
+ # put the prefixes back on the start
76
+ paginated_query = "#{self.prefixes} #{paginated_query}" if self.prefixes
77
+
78
+ # return the paginated version
79
+ PublishMyData::SparqlQuery.new(paginated_query, self.request_format, self) # pass in the original query
80
+ end
81
+
82
+ private
83
+
84
+ def process_sparql_parse_failed_exception_message(bad_sparql_request)
85
+ message = bad_sparql_request.message
86
+ start = message.index(query) + query.size
87
+ finish = message.index('Fuseki')-1 || (message.length-1)
88
+ message[start..finish].strip
89
+ end
90
+
91
+ def select_format_str
92
+ if [:json, :csv, :xml, :text].include?(request_format)
93
+ self.request_format.to_s
94
+ else
95
+ 'text'
96
+ end
97
+ end
98
+
99
+ def ask_format_str
100
+ if [:json, :xml, :text].include?(request_format)
101
+ self.request_format.to_s
102
+ else
103
+ 'text'
104
+ end
105
+ end
106
+
107
+ def construct_or_describe_header
108
+ if [:nt, :ttl, :rdf].include?(request_format)
109
+ Mime::Type.lookup_by_extension( request_format.to_s )
110
+ else
111
+ Mime::NT
112
+ end
113
+ end
114
+
115
+ end
116
+
117
+ end
@@ -0,0 +1,49 @@
1
+ require 'active_support/core_ext/numeric/bytes'
2
+
3
+ module PublishMyData
4
+
5
+ class SparqlQueryResultTooLargeException < StandardError; end
6
+
7
+ # class to wrap up a string sparql result
8
+ class SparqlQueryResult
9
+
10
+ cattr_accessor :MAX_SIZE
11
+ @@MAX_SIZE = 4.megabytes
12
+
13
+ attr_reader :result_str
14
+
15
+ def initialize(result_str)
16
+ @result_str = result_str
17
+
18
+ if self.length > SparqlQueryResult.MAX_SIZE
19
+ raise SparqlQueryResultTooLargeException.new(self.length)
20
+ end
21
+
22
+ end
23
+
24
+ # responds to a bunch of to_x methods to help with rails responders /rendering.
25
+ def length
26
+ self.to_s.length
27
+ end
28
+
29
+ def to_s
30
+ self.result_str
31
+ end
32
+
33
+ [:csv, :nt, :ttl, :rdf, :text].each do |format|
34
+ define_method :"to_#{format.to_s}" do
35
+ self.to_s
36
+ end
37
+ end
38
+
39
+ def to_json(opts={})
40
+ to_s
41
+ end
42
+
43
+ def to_xml(opts={})
44
+ to_s
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,3 @@
1
+ module PublishMyData
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :publish_my_data do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,190 @@
1
+ require 'spec_helper'
2
+
3
+ module PublishMyData
4
+ describe DatasetsController do
5
+
6
+ describe "#show" do
7
+
8
+ let(:dataset) { FactoryGirl.create(:my_dataset) }
9
+
10
+ shared_examples_for "dataset show" do
11
+
12
+ context "for an existing dataset" do
13
+ it "should respond successfully" do
14
+ get :show, id: dataset.slug, use_route: :publish_my_data, :format => format
15
+ response.should be_success
16
+ end
17
+
18
+ it "should set the types variable" do
19
+ get :show, id: dataset.slug, use_route: :publish_my_data, :format => format
20
+ assigns['types'].class.should == Tripod::ResourceCollection
21
+ end
22
+ end
23
+
24
+ context "with a non-existent dataset slug" do
25
+ it "should respond with not found" do
26
+ get :show, id: "slug-that-doesnt-exist", use_route: :publish_my_data, :format => format
27
+ response.should be_not_found
28
+ end
29
+ end
30
+ end
31
+
32
+ shared_examples_for "a non html format" do
33
+
34
+ context "for an existing dataset" do
35
+ it "should return the dataset dtls in that format" do
36
+ get :show, id: dataset.slug, use_route: :publish_my_data, :format => format
37
+ response.body.should == dataset.send("to_#{format}")
38
+ end
39
+ end
40
+
41
+ context "for a non-existent dataset slug" do
42
+ it "should return a blank body" do
43
+ get :show, id: "slug-that-doesnt-exist", use_route: :publish_my_data, :format => format
44
+ response.body.should be_blank
45
+ end
46
+ end
47
+ end
48
+
49
+ context "for rdf format" do
50
+ let(:format){ 'html' }
51
+ it_should_behave_like "dataset show"
52
+ end
53
+
54
+ context "for rdf format" do
55
+ let(:format){ 'rdf' }
56
+ it_should_behave_like "a non html format"
57
+ it_should_behave_like "dataset show"
58
+ end
59
+
60
+ context "for json format" do
61
+ let(:format){ 'json' }
62
+ it_should_behave_like "a non html format"
63
+ it_should_behave_like "dataset show"
64
+ end
65
+
66
+ context "for ttl format" do
67
+ let(:format){ 'ttl' }
68
+ it_should_behave_like "a non html format"
69
+ it_should_behave_like "dataset show"
70
+ end
71
+
72
+ context "for ntriples format" do
73
+ let(:format){ 'nt' }
74
+ it_should_behave_like "a non html format"
75
+ it_should_behave_like "dataset show"
76
+ end
77
+
78
+ end
79
+
80
+ describe "#index" do
81
+
82
+ # make some datasets
83
+ before do
84
+ (1..30).each do |i|
85
+ slug = i
86
+ uri = Dataset.uri_from_slug(slug)
87
+ graph = Dataset.metadata_graph_uri(slug)
88
+ d = PublishMyData::Dataset.new(uri, graph)
89
+ d.title = "Dataset #{i.to_s}"
90
+ d.theme = (i.even? ? 'theme' : 'othertheme')
91
+ d.save!
92
+ end
93
+ end
94
+
95
+ shared_examples_for "a dataset collection in non-html" do
96
+ it "should render the collection in the right format" do
97
+ get :index, :page => page, :per_page => per_page, :format => format, use_route: :publish_my_data
98
+ response.body.should == Dataset.all.limit(per_page).offset(offset).resources.send("to_#{format}")
99
+ end
100
+
101
+ it "shouldn't call Kaminari" do
102
+ Kaminari.should_not_receive(:paginate_array)
103
+ get :index, :page => page, :per_page => per_page, :format => format, use_route: :publish_my_data
104
+ end
105
+
106
+ it "should render successfully" do
107
+ get :index, :page => page, :per_page => per_page, :format => format, use_route: :publish_my_data
108
+ response.should be_success
109
+ end
110
+ end
111
+
112
+ shared_examples_for "dataset kaminari pagination" do
113
+ it "should call kaminari to paginate the results" do
114
+ datasets_array = Dataset.all.limit(per_page).offset(offset).resources.to_a
115
+ count = Dataset.count
116
+
117
+ kam = Kaminari.paginate_array(datasets_array, total_count: count)
118
+
119
+ Kaminari.should_receive(:paginate_array).with(datasets_array, total_count: count).and_return(kam)
120
+ kam.should_receive(:page).with(page).and_return(kam)
121
+ kam.should_receive(:per).with(per_page).and_return(kam)
122
+ get :index, page: page, per_page: per_page, use_route: :publish_my_data
123
+ end
124
+
125
+ it "should set @datasets with the right page of datasets" do
126
+ get :index, page: page, per_page: per_page, use_route: :publish_my_data
127
+ assigns['datasets'].map{ |d| d.uri.to_s }.should ==
128
+ Dataset.all.resources[offset...offset+per_page].map{ |d| d.uri.to_s }
129
+ assigns['datasets'].length.should == per_page
130
+ end
131
+
132
+ end
133
+
134
+ context 'with no pagination params' do
135
+ let(:page) {1}
136
+ let(:per_page) {20}
137
+ let(:offset) { (page-1)*per_page }
138
+
139
+ it "should retreive the first page of results" do
140
+ crit = Dataset.all
141
+ Dataset.should_receive(:all).at_least(:once).and_return(crit)
142
+ crit.should_receive(:limit).with(per_page).and_call_original
143
+ crit.should_receive(:offset).with(offset).and_call_original
144
+ get :index, use_route: :publish_my_data
145
+ end
146
+
147
+ context 'with html format' do
148
+ it_should_behave_like "dataset kaminari pagination"
149
+ end
150
+
151
+ context 'with non-html format' do
152
+ let(:format) {'rdf'}
153
+ it_should_behave_like "a dataset collection in non-html"
154
+ end
155
+ end
156
+
157
+ context 'with pagination params' do
158
+ let(:page) {3}
159
+ let(:per_page) {10}
160
+ let(:offset) { (page-1)*per_page }
161
+
162
+ it "should retreive the right page of results" do
163
+ crit = Dataset.all
164
+ Dataset.should_receive(:all).at_least(:once).and_return(crit)
165
+ crit.should_receive(:limit).with(per_page).and_call_original
166
+ crit.should_receive(:offset).with(offset).and_call_original
167
+ get :index, page: page, per_page: per_page, use_route: :publish_my_data
168
+ end
169
+
170
+ it_should_behave_like "dataset kaminari pagination"
171
+
172
+ context 'with non-html format' do
173
+ let(:format) {'ttl'}
174
+ it_should_behave_like "a dataset collection in non-html"
175
+ end
176
+ end
177
+
178
+ context "with a theme parameter" do
179
+ let(:theme) {'theme'}
180
+
181
+ it "should filter the results to only datasets in the theme" do
182
+ get :index, theme: theme, use_route: :publish_my_data
183
+ assigns['datasets'].length.should == 15 # only the even ones are in this theme
184
+ end
185
+ end
186
+
187
+ end
188
+
189
+ end
190
+ end
@@ -0,0 +1,399 @@
1
+ require 'spec_helper'
2
+
3
+ module PublishMyData
4
+ describe ResourcesController do
5
+
6
+ describe "#id" do
7
+
8
+ context "with html mime type" do
9
+
10
+ before do
11
+ get :id, :path => "this/is/my/path", use_route: :publish_my_data
12
+ end
13
+
14
+ it "should redirect to the corresponding doc view with a 303" do
15
+ response.status.should eq(303)
16
+ response.should redirect_to "/doc/this/is/my/path"
17
+ end
18
+ end
19
+
20
+ context "with an alternative mime type passed in the header" do
21
+ before do
22
+ @request.env['HTTP_ACCEPT'] = "application/rdf+xml"
23
+ get :id, :path => "this/is/my/path", use_route: :publish_my_data
24
+ end
25
+
26
+ it "should keep that mime type when doing the 303" do
27
+ response.status.should eq(303)
28
+ response.should redirect_to "/doc/this/is/my/path"
29
+ response.content_type.should == Mime::RDF
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ describe "#doc" do
36
+
37
+ before do
38
+ @resource = FactoryGirl.create(:yuri_unicorn_resource)
39
+ end
40
+
41
+ it "should respond successfully" do
42
+ get :doc, :path => "unicorns/yuri", use_route: :publish_my_data
43
+ response.should be_success
44
+ end
45
+
46
+ it "should render the show template" do
47
+ get :doc, :path => "unicorns/yuri", use_route: :publish_my_data
48
+ response.should render_template("publish_my_data/resources/show")
49
+ end
50
+
51
+ context "for html" do
52
+ it "should eager load the labels" do
53
+ Resource.should_receive(:find).and_return(@resource)
54
+ @resource.should_receive(:eager_load_predicate_triples!)
55
+ @resource.should_receive(:eager_load_object_triples!)
56
+ get :doc, :path => "unicorns/yuri", use_route: :publish_my_data
57
+ end
58
+ end
59
+
60
+ context "with an alternative mime type passed in the header" do
61
+
62
+ before do
63
+ @request.env['HTTP_ACCEPT'] = "application/rdf+xml"
64
+ get :doc, :path => "unicorns/yuri", use_route: :publish_my_data
65
+ end
66
+
67
+ it "should resond with the right mime type" do
68
+ response.content_type.should == Mime::RDF
69
+ end
70
+
71
+ it "should respond with the right content" do
72
+ response.body.should == @resource.to_rdf
73
+ end
74
+
75
+ it "should not eager load the labels" do
76
+ Resource.should_receive(:find).and_return(@resource)
77
+ @resource.should_not_receive(:eager_load_predicate_triples!)
78
+ @resource.should_not_receive(:eager_load_object_triples!)
79
+ get :doc, :path => "unicorns/yuri", use_route: :publish_my_data
80
+ end
81
+
82
+ context "and the resource doesn't exist" do
83
+ it "should 404 with a blank response" do
84
+ get :doc, :path => "unicorns/borat", use_route: :publish_my_data
85
+ response.should be_not_found
86
+ response.body.should be_blank
87
+ end
88
+ end
89
+
90
+ end
91
+
92
+ context "with an alternative format passed on the url" do
93
+
94
+ it "should resond with the right mime type" do
95
+ get :doc, :path => "unicorns/yuri", format: 'ttl', use_route: :publish_my_data
96
+ response.content_type.should == Mime::TTL
97
+ end
98
+
99
+ it "should respond with the right content" do
100
+ get :doc, :path => "unicorns/yuri", format: 'ttl', use_route: :publish_my_data
101
+ response.body.should == @resource.to_ttl
102
+ end
103
+
104
+ end
105
+
106
+ context "when resource doesn't exist" do
107
+
108
+ before do
109
+ get :doc, :path => "doesnt/exist", use_route: :publish_my_data
110
+ end
111
+
112
+ it "should 404" do
113
+ response.should be_not_found
114
+ end
115
+
116
+ end
117
+
118
+ end
119
+
120
+ describe "#definition" do
121
+
122
+ before do
123
+ @resource = FactoryGirl.create(:mean_result)
124
+ end
125
+
126
+ context "for resource in our database" do
127
+
128
+ it "should respond successfully" do
129
+ get :definition, :path => "statistics/meanResult", use_route: :publish_my_data
130
+ response.should be_success
131
+ end
132
+
133
+ it "should render the doc template" do
134
+ get :definition, :path => "statistics/meanResult", use_route: :publish_my_data
135
+ response.should render_template("publish_my_data/resources/show")
136
+ end
137
+
138
+ context "with an alternative mime type" do
139
+ it "should with the right mime type and content" do
140
+ get :definition, :path => "statistics/meanResult", :format => 'nt', use_route: :publish_my_data
141
+ response.content_type.should == Mime::NT
142
+ response.body.should == @resource.to_nt
143
+ end
144
+ end
145
+
146
+ end
147
+
148
+ context "when resource doesn't exist" do
149
+ it "should 404" do
150
+ get :definition, :path => "statistics/nonExistent", use_route: :publish_my_data
151
+ response.should be_not_found
152
+ end
153
+ end
154
+
155
+ end
156
+
157
+ describe "#show" do
158
+
159
+ context "with a resource not in our database" do
160
+
161
+ uri = "http://purl.org/linked-data/sdmx/2009/dimension%23refArea"
162
+
163
+ context "html mime type" do
164
+
165
+ before do
166
+ get :show, :uri => uri, use_route: :publish_my_data
167
+ end
168
+
169
+ context "with resource not in our database" do
170
+ it "should redirect to the external uri" do
171
+ response.should redirect_to('http://purl.org/linked-data/sdmx/2009/dimension%23refArea')
172
+ end
173
+ end
174
+
175
+ end
176
+
177
+ context "non html mime type" do
178
+
179
+ before do
180
+ get :show, :uri => uri, :format => 'rdf', use_route: :publish_my_data
181
+ end
182
+
183
+ it "should 404" do
184
+ response.should be_not_found
185
+ end
186
+ end
187
+ end
188
+
189
+ context "with a resource in our database" do
190
+
191
+ before do
192
+ uri = 'http://uri'
193
+ graph = 'http://graph'
194
+ r = Resource.new(uri, graph)
195
+ r.write_predicate('http://foo', 'blah')
196
+ r.save!
197
+
198
+ get :show, :uri => r.uri, use_route: :publish_my_data
199
+ end
200
+
201
+ it "should respond succesfully" do
202
+ response.should be_success
203
+ end
204
+
205
+ it "should render the show template" do
206
+ response.should render_template("publish_my_data/resources/show")
207
+ end
208
+
209
+ end
210
+ end
211
+
212
+ describe "#index" do
213
+
214
+ shared_examples_for "resource kaminari pagination" do
215
+ it "should call kaminari to paginate the results" do
216
+ res_array = Resource.all.limit(per_page).offset(offset).resources.to_a
217
+ count = Resource.count
218
+
219
+ kam = Kaminari.paginate_array(res_array, total_count: count)
220
+
221
+ Kaminari.should_receive(:paginate_array).with(res_array, total_count: count).and_return(kam)
222
+ kam.should_receive(:page).with(page).and_return(kam)
223
+ kam.should_receive(:per).with(per_page).and_return(kam)
224
+ get :index, page: page, per_page: per_page, use_route: :publish_my_data
225
+ end
226
+
227
+ it "should set @resources with the right page of datasets" do
228
+ get :index, page: page, per_page: per_page, use_route: :publish_my_data
229
+ assigns['resources'].map{ |d| d.uri.to_s }.should ==
230
+ Resource.all.resources[offset...offset+per_page].map{ |r| r.uri.to_s }
231
+ assigns['resources'].length.should == per_page
232
+ end
233
+ end
234
+
235
+ shared_examples_for "a resource collection in non-html" do
236
+ it "should render the collection in the right format" do
237
+ get :index, :page => page, :per_page => per_page, :format => format, use_route: :publish_my_data
238
+ response.body.should == Resource.all.limit(per_page).offset(offset).resources.send("to_#{format}")
239
+ end
240
+
241
+ it "shouldn't call Kaminari" do
242
+ Kaminari.should_not_receive(:paginate_array)
243
+ get :index, :page => page, :per_page => per_page, :format => format, use_route: :publish_my_data
244
+ end
245
+
246
+ it "should render successfully" do
247
+ get :index, :page => page, :per_page => per_page, :format => format, use_route: :publish_my_data
248
+ response.should be_success
249
+ end
250
+ end
251
+
252
+ let(:dataset) { FactoryGirl.create(:my_dataset) }
253
+
254
+ let(:type) do
255
+ t = PublishMyData::RdfType.new('http://i-am-a-type', 'http://types')
256
+ t.label = 'I am a type'
257
+ t.save!
258
+ t
259
+ end
260
+
261
+ before do
262
+
263
+ # make some resources (in and out of our dataset and type)
264
+ (1..5).each do |i|
265
+ r = Resource.new("http://resource-in-ds/#{i}", dataset.data_graph_uri)
266
+ r.label = "resource #{i}"
267
+ r.write_predicate(RDF.type, RDF::URI.new(type.uri)) if i.even?
268
+ r.save!
269
+ end
270
+
271
+ (1..3).each do |i|
272
+ r = Resource.new("http://resource-not-in-ds/#{i}", 'http://anothergraph')
273
+ r.label = "resource #{i}"
274
+ r.write_predicate(RDF.type, RDF::URI.new(type.uri)) if i.even?
275
+ r.save!
276
+ end
277
+ end
278
+
279
+ it 'should set the resources variable' do
280
+ get :index, use_route: :publish_my_data
281
+ assigns['resources'].should_not be_blank
282
+ end
283
+
284
+ context "with no parameters" do
285
+ it "should respond successfully" do
286
+ get :index, use_route: :publish_my_data
287
+ end
288
+
289
+ it "should return paginated results for Resource.all" do
290
+ subject.should_receive(:paginate_resources).with(Resource.all).and_call_original
291
+ get :index, use_route: :publish_my_data
292
+ assigns['resources'].length.should == 10 # 8 resources, plus ds and type!
293
+ end
294
+ end
295
+
296
+ context 'with pagination params' do
297
+ let(:page) {2}
298
+ let(:per_page) {2}
299
+ let(:offset) { (page-1)*per_page }
300
+
301
+ it "should retreive the right page of results" do
302
+ crit = Resource.all
303
+ Resource.should_receive(:all).at_least(:once).and_return(crit)
304
+ crit.should_receive(:limit).with(per_page).and_call_original
305
+ crit.should_receive(:offset).with(offset).and_call_original
306
+ get :index, page: page, per_page: per_page, use_route: :publish_my_data
307
+ end
308
+
309
+ it_should_behave_like "resource kaminari pagination"
310
+
311
+ context 'with non-html format' do
312
+ let(:format) {'ttl'}
313
+ it_should_behave_like "a resource collection in non-html"
314
+ end
315
+ end
316
+
317
+ context 'with a type parameter' do
318
+ context 'where the type exists' do
319
+ before do
320
+ get :index, type_uri: type.uri, use_route: :publish_my_data
321
+ end
322
+
323
+ it 'should filter the results by things of that type' do
324
+ assigns['resources'].length.should == 3
325
+ end
326
+
327
+ it 'should set the type filter variable' do
328
+ assigns['type_filter'].should == type.uri
329
+ end
330
+
331
+ it 'should set the dataset variable to the dataset' do
332
+ assigns['type'].should == type
333
+ end
334
+ end
335
+
336
+ context 'where the type does not exist' do
337
+ before do
338
+ get :index, type_uri: 'bleh', use_route: :publish_my_data
339
+ end
340
+
341
+ it 'should not find any results' do
342
+ assigns['resources'].length.should == 0
343
+ end
344
+
345
+ it 'should set the type filter variable' do
346
+ assigns['type_filter'].should == 'bleh'
347
+ end
348
+
349
+ it 'should not set the type variable' do
350
+ assigns['type'].should be_nil
351
+ end
352
+ end
353
+ end
354
+
355
+ context "with a dataset parameter" do
356
+ context 'where the dataset exists' do
357
+
358
+ before do
359
+ get :index, dataset: dataset.slug, use_route: :publish_my_data
360
+ end
361
+
362
+ it "should filter the results by datasets with that slug" do
363
+ assigns['resources'].length.should == 5
364
+ end
365
+
366
+ it 'should set the dataset filter variable' do
367
+ assigns['dataset_filter'].should == dataset.slug
368
+ end
369
+
370
+ it 'should set the dataset variable to the dataset' do
371
+ assigns['dataset'].should == dataset
372
+ end
373
+
374
+ end
375
+
376
+ context 'where the dataset does not exist' do
377
+ before do
378
+ get :index, dataset: 'bleh', use_route: :publish_my_data
379
+ end
380
+
381
+ it 'should not find any results' do
382
+ assigns['resources'].length.should == 0
383
+ end
384
+
385
+ it 'should set the dataset filter variable' do
386
+ assigns['dataset_filter'].should == 'bleh'
387
+ end
388
+
389
+ it 'should not set the dataset variable to the dataset' do
390
+ assigns['dataset'].should be_nil
391
+ end
392
+ end
393
+ end
394
+ end
395
+
396
+
397
+
398
+ end
399
+ end