publish_my_data 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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