nice 0.0.7 → 1.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.
@@ -0,0 +1,105 @@
1
+ require 'httparty'
2
+
3
+ require_relative 'organization'
4
+ require_relative 'resource'
5
+ require_relative 'dataset'
6
+
7
+ module Nice
8
+ module DataGouv
9
+ class Client
10
+ include HTTParty
11
+ base_uri 'https://www.data.gouv.fr/api/1'
12
+ follow_redirects true
13
+
14
+ attr_reader :api_key
15
+
16
+ # Manually curated list of organization slugs for the Nice Côte d'Azur region, sorted alphabetically.
17
+ ORGANIZATION_SLUGS = %w[
18
+ association-mediterraneenne-de-secourisme-du-06-1
19
+ banque-populaire-mediterranee
20
+ communaute-dagglomeration-cannes-lerins-1
21
+ communaute-urbaine-nice-cote-dazur
22
+ commune-de-cagnes-sur-mer
23
+ commune-de-fontan
24
+ compagnie-autobus-de-monaco
25
+ compagnie-des-autobus-de-monaco
26
+ conseil-departemental-du-var
27
+ ddtm-alpes-maritimes
28
+ departement-des-alpes-maritimes
29
+ eau-dazur
30
+ ecole-nationale-superieure-d-art-villa-arson-de-nice
31
+ groupement-dassociations-de-defense-de-lenvironnement-et-des-sites-de-la-cote-dazur
32
+ innovevents-reseau-national-dagences-evenementielles
33
+ mairie-de-cannes
34
+ mairie-de-grasse
35
+ mairie-de-la-gaude
36
+ metropole-toulon-provence-mediterranee
37
+ nice-cote-dazur
38
+ office-de-tourisme-metropolitain-nice-cote-dazur
39
+ parc-national-de-port-cros
40
+ prise-de-nice-1
41
+ regie-ligne-dazur
42
+ service-departemental-dincendie-et-de-secours-des-alpes-maritimes
43
+ sictiam
44
+ ville-dantibes
45
+ ville-de-frejus
46
+ ville-de-nice
47
+ ]
48
+
49
+ def initialize(api_key: nil)
50
+ @api_key = api_key || ENV['DATA_GOUV_API_KEY']
51
+ end
52
+
53
+ # Get organization by ID or slug
54
+ def organization(id_or_slug)
55
+ response = self.class.get("/organizations/#{id_or_slug}", headers: headers)
56
+ handle_response(response) do |data|
57
+ Organization.new(data)
58
+ end
59
+ end
60
+
61
+ # List organization datasets
62
+ def organization_datasets(org_id_or_slug, page: 1, page_size: 20)
63
+ response = self.class.get(
64
+ "/organizations/#{org_id_or_slug}/datasets",
65
+ query: { page: page, page_size: page_size },
66
+ headers: headers
67
+ )
68
+ handle_response(response) do |data|
69
+ (data['data'] || []).map { |d| Dataset.new(d) }
70
+ end
71
+ end
72
+
73
+ # Get dataset by ID or slug
74
+ def dataset(id_or_slug)
75
+ response = self.class.get("/datasets/#{id_or_slug}/", headers: headers)
76
+ handle_response(response) do |data|
77
+ Dataset.new(data)
78
+ end
79
+ end
80
+
81
+ private
82
+
83
+ def headers
84
+ headers = { 'Accept' => 'application/json' }
85
+ headers['X-API-KEY'] = @api_key if @api_key
86
+ headers
87
+ end
88
+
89
+ def handle_response(response)
90
+ case response.code
91
+ when 200
92
+ yield response.parsed_response
93
+ when 404
94
+ raise Nice::APIError, "Resource not found"
95
+ when 401, 403
96
+ raise Nice::APIError, "Authentication failed or access denied"
97
+ else
98
+ raise Nice::APIError, "API request failed with status #{response.code}: #{response.body}"
99
+ end
100
+ rescue JSON::ParserError => e
101
+ raise Nice::APIError, "Failed to parse API response: #{e.message}"
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,42 @@
1
+ require_relative 'organization'
2
+ require_relative 'resource'
3
+
4
+ module Nice
5
+ module DataGouv
6
+ class Dataset
7
+ attr_reader :id, :name, :title, :notes, :organization, :resources, :tags, :created_at, :metadata_modified
8
+
9
+ def initialize(attributes = {})
10
+ @id = attributes['id']
11
+ @name = attributes['name']
12
+ @title = attributes['title']
13
+ @notes = attributes['notes']
14
+ @created_at = attributes['metadata_created']
15
+ @metadata_modified = attributes['metadata_modified']
16
+ @tags = (attributes['tags'] || []).map { |t| t.is_a?(Hash) ? t['name'] : t }
17
+
18
+ @organization = if attributes['organization']
19
+ Organization.new(attributes['organization'])
20
+ end
21
+
22
+ @resources = (attributes['resources'] || []).map do |resource_data|
23
+ Resource.new(resource_data)
24
+ end
25
+ end
26
+
27
+ def to_h
28
+ {
29
+ 'id' => @id,
30
+ 'name' => @name,
31
+ 'title' => @title,
32
+ 'notes' => @notes,
33
+ 'organization' => @organization&.to_h,
34
+ 'resources' => @resources.map(&:to_h),
35
+ 'tags' => @tags,
36
+ 'created_at' => @created_at,
37
+ 'metadata_modified' => @metadata_modified
38
+ }
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,29 @@
1
+ module Nice
2
+ module DataGouv
3
+ class Organization
4
+ attr_reader :id, :name, :slug, :title, :description, :image_url, :created_at
5
+
6
+ def initialize(attributes = {})
7
+ @id = attributes['id']
8
+ @name = attributes['name']
9
+ @slug = attributes['slug']
10
+ @title = attributes['title'] || attributes['display_name'] || attributes['name']
11
+ @description = attributes['description']
12
+ @image_url = attributes['logo'] || attributes['image_url'] || attributes['image_display_url']
13
+ @created_at = attributes['created_at'] || attributes['created']
14
+ end
15
+
16
+ def to_h
17
+ {
18
+ 'id' => @id,
19
+ 'name' => @name,
20
+ 'slug' => @slug,
21
+ 'title' => @title,
22
+ 'description' => @description,
23
+ 'image_url' => @image_url,
24
+ 'created_at' => @created_at
25
+ }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+ module Nice
2
+ module DataGouv
3
+ class Resource
4
+ attr_reader :id, :name, :description, :url, :format, :size, :created_at, :last_modified
5
+
6
+ def initialize(attributes = {})
7
+ @id = attributes['id']
8
+ @name = attributes['name']
9
+ @description = attributes['description']
10
+ @url = attributes['url']
11
+ @format = attributes['format']
12
+ @size = attributes['size']
13
+ @created_at = attributes['created']
14
+ @last_modified = attributes['last_modified']
15
+ end
16
+
17
+ def to_h
18
+ {
19
+ 'id' => @id,
20
+ 'name' => @name,
21
+ 'description' => @description,
22
+ 'url' => @url,
23
+ 'format' => @format,
24
+ 'size' => @size,
25
+ 'created_at' => @created_at,
26
+ 'last_modified' => @last_modified
27
+ }
28
+ end
29
+ end
30
+ end
31
+ end
data/lib/nice/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Nice
2
- VERSION = "0.0.7"
4
+ VERSION = '1.0.1'
3
5
  end
data/lib/nice.rb CHANGED
@@ -1,5 +1,36 @@
1
- require 'nice/middleware'
2
- require 'nice/engine'
1
+ require 'ckan'
2
+
3
+ require_relative 'nice/client'
4
+ require_relative 'nice/version'
5
+
6
+ require_relative 'nice/data_gouv/client'
3
7
 
4
8
  module Nice
9
+ class Error < StandardError; end
10
+ class ConfigurationError < Error; end
11
+ class APIError < Error; end
12
+
13
+ class << self
14
+ attr_accessor :configuration
15
+ end
16
+
17
+ def self.configure
18
+ self.configuration ||= Configuration.new
19
+ yield(configuration)
20
+ end
21
+
22
+ class Configuration
23
+ attr_accessor :ckan_url, :api_key
24
+
25
+ def initialize
26
+ @ckan_url = ENV['NICE_CKAN_URL'] || 'https://opendata.nicecotedazur.org/data/'
27
+
28
+ @api_key = ENV['NICE_CKAN_API_KEY']
29
+ end
30
+
31
+ def validate!
32
+ raise ConfigurationError, "CKAN URL is required" if ckan_url.nil? || ckan_url.empty?
33
+ raise ConfigurationError, "API key is required" if api_key.nil? || api_key.empty?
34
+ end
35
+ end
5
36
  end
data/nice.gemspec ADDED
@@ -0,0 +1,43 @@
1
+ require_relative "lib/nice/version"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "nice"
5
+ spec.version = Nice::VERSION
6
+ spec.authors = ["Nicolas Leger"]
7
+ spec.email = ["nicolasleger@users.noreply.github.com"]
8
+
9
+ spec.summary = "OpenData NCA - Métropole Nice Côte d'Azur"
10
+ spec.description = "A Ruby gem for accessing and managing OpenData from Nice Côte d'Azur metropolitan area via CKAN API"
11
+ spec.homepage = "https://github.com/nicolasleger/nice"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = ">= 2.7.0"
14
+
15
+ spec.metadata["homepage_uri"] = spec.homepage
16
+ spec.metadata["source_code_uri"] = "https://github.com/nicolasleger/nice"
17
+ spec.metadata["changelog_uri"] = "https://github.com/nicolasleger/nice/blob/main/CHANGELOG.md"
18
+
19
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
20
+ `git ls-files -z`.split("\x0").reject do |f|
21
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
22
+ end
23
+ end
24
+ spec.bindir = "exe"
25
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
26
+ spec.require_paths = ["lib"]
27
+
28
+ # CKAN dependency
29
+ spec.add_dependency "ckan"
30
+
31
+ # Additional useful dependencies
32
+ spec.add_dependency "httparty", "~> 0.21"
33
+ spec.add_dependency "json", "~> 2.6"
34
+
35
+ # Development dependencies
36
+ spec.add_development_dependency "rake", "~> 13.0"
37
+ spec.add_development_dependency "rspec", "~> 3.12"
38
+ spec.add_development_dependency "rubocop", "~> 1.50"
39
+ spec.add_development_dependency "vcr", "~> 6.0"
40
+ spec.add_development_dependency "webmock", "~> 3.0"
41
+ spec.add_development_dependency "pry", "~> 0.14"
42
+ spec.add_development_dependency "pry-byebug", "~> 3.10"
43
+ end
@@ -0,0 +1,9 @@
1
+ {
2
+ "packages": {
3
+ ".": {
4
+ "package-name": "nice",
5
+ "version-file": "lib/nice/version.rb",
6
+ "extra-files": ["Gemfile.lock"]
7
+ }
8
+ }
9
+ }
metadata CHANGED
@@ -1,118 +1,201 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nice
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
5
- prerelease:
4
+ version: 1.0.1
6
5
  platform: ruby
7
6
  authors:
8
- - Benjamin Mueller
9
- autorequire:
10
- bindir: bin
7
+ - Nicolas Leger
8
+ bindir: exe
11
9
  cert_chain: []
12
- date: 2013-02-18 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
13
11
  dependencies:
14
12
  - !ruby/object:Gem::Dependency
15
- name: rails
13
+ name: ckan
16
14
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
15
  requirements:
19
- - - ~>
16
+ - - ">="
20
17
  - !ruby/object:Gem::Version
21
- version: 3.2.3
18
+ version: '0'
22
19
  type: :runtime
23
20
  prerelease: false
24
21
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
22
  requirements:
27
- - - ~>
23
+ - - ">="
28
24
  - !ruby/object:Gem::Version
29
- version: 3.2.3
25
+ version: '0'
30
26
  - !ruby/object:Gem::Dependency
31
- name: nokogiri
27
+ name: httparty
32
28
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
29
  requirements:
35
- - - ! '>='
30
+ - - "~>"
36
31
  - !ruby/object:Gem::Version
37
- version: '0'
32
+ version: '0.21'
38
33
  type: :runtime
39
34
  prerelease: false
40
35
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
36
  requirements:
43
- - - ! '>='
37
+ - - "~>"
44
38
  - !ruby/object:Gem::Version
45
- version: '0'
39
+ version: '0.21'
46
40
  - !ruby/object:Gem::Dependency
47
- name: sqlite3
41
+ name: json
48
42
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
43
  requirements:
51
- - - ! '>='
44
+ - - "~>"
52
45
  - !ruby/object:Gem::Version
53
- version: '0'
46
+ version: '2.6'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '2.6'
54
+ - !ruby/object:Gem::Dependency
55
+ name: rake
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '13.0'
54
61
  type: :development
55
62
  prerelease: false
56
63
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
64
  requirements:
59
- - - ! '>='
65
+ - - "~>"
60
66
  - !ruby/object:Gem::Version
61
- version: '0'
62
- description: Seriously, it's a nice little state engine for JS/HTML5 on Rails
67
+ version: '13.0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: rspec
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.12'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.12'
82
+ - !ruby/object:Gem::Dependency
83
+ name: rubocop
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '1.50'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '1.50'
96
+ - !ruby/object:Gem::Dependency
97
+ name: vcr
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '6.0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '6.0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: webmock
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '3.0'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '3.0'
124
+ - !ruby/object:Gem::Dependency
125
+ name: pry
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '0.14'
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '0.14'
138
+ - !ruby/object:Gem::Dependency
139
+ name: pry-byebug
140
+ requirement: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '3.10'
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '3.10'
152
+ description: A Ruby gem for accessing and managing OpenData from Nice Côte d'Azur
153
+ metropolitan area via CKAN API
63
154
  email:
64
- - elchbenny@googlemail.com
155
+ - nicolasleger@users.noreply.github.com
65
156
  executables: []
66
157
  extensions: []
67
158
  extra_rdoc_files: []
68
159
  files:
69
- - lib/assets/javascripts/event_dispatcher.coffee
70
- - lib/assets/javascripts/nice_imp_jquery.js.coffee
71
- - lib/assets/javascripts/nice_jquery.js
72
- - lib/nice/config.rb
73
- - lib/nice/engine.rb
74
- - lib/nice/html_parser.rb
75
- - lib/nice/js/caller.rb
76
- - lib/nice/logic.rb
77
- - lib/nice/middleware.rb
78
- - lib/nice/version.rb
79
- - lib/nice.rb
80
- - lib/tasks/nice_tasks.rake
81
- - MIT-LICENSE
82
- - Rakefile
160
+ - ".release-please-manifest.json"
161
+ - ".rspec"
162
+ - CHANGELOG.md
163
+ - Gemfile
164
+ - Gemfile.lock
165
+ - LICENSE
83
166
  - README.md
84
- - test/integration/nice_test.rb
85
- - test/test_helper.rb
86
- homepage: ''
87
- licenses: []
88
- post_install_message:
167
+ - Rakefile
168
+ - lib/nice.rb
169
+ - lib/nice/client.rb
170
+ - lib/nice/data_gouv/client.rb
171
+ - lib/nice/data_gouv/dataset.rb
172
+ - lib/nice/data_gouv/organization.rb
173
+ - lib/nice/data_gouv/resource.rb
174
+ - lib/nice/version.rb
175
+ - nice.gemspec
176
+ - release-please-config.json
177
+ homepage: https://github.com/nicolasleger/nice
178
+ licenses:
179
+ - MIT
180
+ metadata:
181
+ homepage_uri: https://github.com/nicolasleger/nice
182
+ source_code_uri: https://github.com/nicolasleger/nice
183
+ changelog_uri: https://github.com/nicolasleger/nice/blob/main/CHANGELOG.md
89
184
  rdoc_options: []
90
185
  require_paths:
91
186
  - lib
92
187
  required_ruby_version: !ruby/object:Gem::Requirement
93
- none: false
94
188
  requirements:
95
- - - ! '>='
189
+ - - ">="
96
190
  - !ruby/object:Gem::Version
97
- version: '0'
98
- segments:
99
- - 0
100
- hash: 3851994827556330401
191
+ version: 2.7.0
101
192
  required_rubygems_version: !ruby/object:Gem::Requirement
102
- none: false
103
193
  requirements:
104
- - - ! '>='
194
+ - - ">="
105
195
  - !ruby/object:Gem::Version
106
196
  version: '0'
107
- segments:
108
- - 0
109
- hash: 3851994827556330401
110
197
  requirements: []
111
- rubyforge_project:
112
- rubygems_version: 1.8.24
113
- signing_key:
114
- specification_version: 3
115
- summary: Nice / Nizza is a posh little town in south France.
116
- test_files:
117
- - test/integration/nice_test.rb
118
- - test/test_helper.rb
198
+ rubygems_version: 4.0.3
199
+ specification_version: 4
200
+ summary: OpenData NCA - Métropole Nice Côte d'Azur
201
+ test_files: []
data/MIT-LICENSE DELETED
@@ -1,20 +0,0 @@
1
- Copyright 2012 YOURNAME
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,34 +0,0 @@
1
- class this.NiceEventDispatcher
2
-
3
- # state transition cache
4
- @state_cache
5
-
6
- # gets called by JS response and generates JS events either dispatched immediatly
7
- # or later by another transition event
8
- @dispatch_event: (event_name, attrs, cached = false, transition_id = null) ->
9
- # create event
10
- evt = document.createEvent("Event")
11
- evt.initEvent(event_name,true,true);
12
-
13
- # add remaining arguments as event properties
14
- evt[key] = value for key, value of attrs
15
-
16
- if cached == true # is this state preloading?
17
- if !NiceEventDispatcher.state_cache?[transition_id]?
18
- NiceEventDispatcher.state_cache = new Object;
19
- NiceEventDispatcher.state_cache[transition_id] = []
20
- document.addEventListener "nice.state.CachedTransitionEvent", NiceEventDispatcher.dispatch_cached_transition_events, false
21
-
22
- NiceEventDispatcher.state_cache[transition_id].push evt
23
- else # dispatch
24
- document.dispatchEvent(evt)
25
-
26
- # launch cached state transition
27
- @dispatch_cached_transition_events: (event) ->
28
- if NiceEventDispatcher.state_cache?[event.transition_id]?
29
-
30
- # fire stored events
31
- document.dispatchEvent(evt) for evt in NiceEventDispatcher.state_cache[event.transition_id]
32
-
33
- # clean/reset
34
- NiceEventDispatcher.state_cache[event.transition_id] = null