wikidatum 0.2.1 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 50ad5328f1593f1de47d492e6c4e761d80d3e43bb967bcf9386f72053881b705
4
- data.tar.gz: eb17d97dfdbe7c45c2b10bc7d34aeeb76136b3473c72817f7a1b053f0e2d16eb
3
+ metadata.gz: d2ee435a3831b816e6e64465040a5197de654450551812b835b28329be9c287d
4
+ data.tar.gz: d23fb1902df5465b123fc0bcea0c7594fb64a6e918604a9f1bb1f4e4eadf6eff
5
5
  SHA512:
6
- metadata.gz: f6cb6a7968e9f8943b6b6cd06311d74139a8580dde6e925a83cdf891292d5e6028a63b027394af2b04b31cadc78af88170f3a3fd3c92c2d4aeaca72560048402
7
- data.tar.gz: d27a8240fec4fd41caa3ec21ce7bab706fed304bd364b076c741b7577bc04ce1fdd3df5db1675a5cbc431872ad1fe69f7f7b035a696b6212a38a97afec3bc2c6
6
+ metadata.gz: ccd8210a5120fbbfb35ed03899938bf4ca4e5302bc93e3e53652180b86b221a3ec23afe57db78777ffcda5971150f7c0ed6af89cde7b294fe21d716491653c49
7
+ data.tar.gz: cb4e092b80c6ab871c1dd7f5bd46f700029eab7438c7a4063a2aee42b389c0e86ec0e387fc15fa996037d2478f494ac46572879078930c41c18ae6b7e4073e00
data/CHANGELOG.md CHANGED
@@ -6,8 +6,29 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## 0.3.1 - 2022-12-28
10
+ ### Added
11
+
12
+ - Add an error message when attempting to make a bot edit without authentication, as this will always trigger a 403 error from the REST API.
13
+
14
+ ### Fixed
15
+
16
+ - Fix the creation of WikibaseItem statements, the format used in the previous release was incorrect.
17
+
18
+ ## 0.3.0 - 2022-12-27
19
+ ### Added
20
+
21
+ - Add `allow_ip_edits` argument on `Wikidatum::Client.new`. This protects users from making IP address-exposing edits if they haven't explicitly opted-in to doing that. The argument defaults to false.
22
+ - Add code to raise errors when various types of invalid input are passed to `Wikidatum::Client#add_statement`.
23
+ - Start testing the gem on Ruby 3.2.
24
+
25
+ ### Fixed
26
+
27
+ - Update the serializers and `add_statement` method to account for various changes that have been made upstream to the Wikibase REST API.
28
+
9
29
  ## 0.2.1 - 2022-08-13
10
30
  ### Fixed
31
+
11
32
  - Fix a mistake that broke loading the gem.
12
33
 
13
34
  ## 0.2.0 - 2022-08-13
@@ -28,4 +49,3 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
28
49
  ### Added
29
50
 
30
51
  - Initial release, nothing is really usable yet.
31
-
data/README.md CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  This gem supports making requests to the [new Wikidata/Wikibase REST API](https://doc.wikimedia.org/Wikibase/master/js/rest-api/).
4
4
 
5
- **The gem is currently in very early development and is not ready for production usage**.
5
+ The [Wikimedia Docs on Wikibase's JSON format](https://doc.wikimedia.org/Wikibase/master/php/docs_topics_json.html) are also very useful for interacting with/contributing to this gem.
6
+
7
+ **The gem is currently in early development and is not ready for production usage**.
6
8
 
7
9
  ## Installation
8
10
 
@@ -24,7 +26,7 @@ Or install it yourself as:
24
26
 
25
27
  You can view the YARD docs on GitHub Pages [here](https://connorshea.github.io/wikidatum/index.html).
26
28
 
27
- Currently, the gem is able to hit a few GET endpoints, and currently has no way to provide authentication and perform POST/PUT/DELETE requests. The additional features will be added later.
29
+ Currently, the gem is able to hit a few of the basic endpoints, and currently has no way to provide authentication. The additional features will be added later.
28
30
 
29
31
  ```ruby
30
32
  require 'wikidatum'
@@ -57,6 +59,26 @@ item.label(lang: :en).value #=> "Earth"
57
59
 
58
60
  # Get the values for all English aliases on this item.
59
61
  item.aliases(langs: [:en]).map(&:value) #=> ["Planet Earth", "Pale Blue Dot"]
62
+
63
+ statement_id = 'Q123$4543523c-1d1d-1111-1e1e-11b11111b1f1'
64
+ statement = wikidatum_client.statement(id: statement_id) #=> Wikidatum::Statement
65
+
66
+ # Add a statement to Q193581 for P577 (publication date) that has a time value of November 16, 2004.
67
+ wikidatum_client.add_statement(
68
+ id: 'Q193581',
69
+ property: 'P577',
70
+ value: Wikidatum::DataType::Time.new(
71
+ time: '+2004-11-16T00:00:00Z',
72
+ precision: 11,
73
+ calendar_model: 'https://www.wikidata.org/entity/Q12138'
74
+ )
75
+ )
76
+
77
+ # Delete a statement and include an edit summary.
78
+ wikidatum_client.delete_statement(
79
+ id: 'Q123$4543523c-1d1d-1111-1e1e-11b11111b1f1',
80
+ comment: 'Deleting this statement because it is inaccurate.'
81
+ )
60
82
  ```
61
83
 
62
84
  ## Development
@@ -6,7 +6,19 @@ require 'faraday/net_http'
6
6
  module Wikidatum
7
7
  class Client
8
8
  ITEM_REGEX = /^Q?\d+$/.freeze
9
+ PROPERTY_REGEX = /^P?\d+$/.freeze
9
10
  STATEMENT_REGEX = /^Q?\d+\$[\w-]+$/.freeze
11
+ VALID_RANKS = ['preferred', 'normal', 'deprecated'].freeze
12
+ VALID_DATA_TYPES = [
13
+ 'Wikidatum::DataType::GlobeCoordinate',
14
+ 'Wikidatum::DataType::MonolingualText',
15
+ 'Wikidatum::DataType::NoValue',
16
+ 'Wikidatum::DataType::Quantity',
17
+ 'Wikidatum::DataType::SomeValue',
18
+ 'Wikidatum::DataType::Time',
19
+ 'Wikidatum::DataType::WikibaseItem',
20
+ 'Wikidatum::DataType::WikibaseString'
21
+ ].freeze
10
22
 
11
23
  # @return [String] the root URL of the Wikibase instance we want to interact
12
24
  # with. If not provided, will default to Wikidata.
@@ -20,31 +32,41 @@ module Wikidatum
20
32
  # Wikibase API.
21
33
  attr_reader :user_agent
22
34
 
35
+ # @return [Boolean] whether this client should allow non-GET requests if
36
+ # authentication hasn't been provided. Defaults to false.
37
+ attr_reader :allow_ip_edits
38
+
23
39
  # Create a new Wikidatum::Client to interact with the Wikibase REST API.
24
40
  #
25
41
  # @example
26
42
  # wikidatum_client = Wikidatum::Client.new(
27
- # user_agent: 'REPLACE ME WITH THE NAME OF YOUR BOT!',
43
+ # user_agent: 'Bot Name',
28
44
  # wikibase_url: 'https://www.wikidata.org',
29
45
  # bot: true
30
46
  # )
31
47
  #
32
48
  # @param user_agent [String] The UserAgent header to send with all requests
33
- # to the Wikibase API.
49
+ # to the Wikibase API. This will be prepended with the string "Wikidatum
50
+ # Ruby gem vX.X.X:".
34
51
  # @param wikibase_url [String] The root URL of the Wikibase instance we want
35
52
  # to interact with. If not provided, will default to
36
53
  # `https://www.wikidata.org`. Do not include a `/` at the end of the URL.
37
54
  # @param bot [Boolean] Whether requests sent by this client instance should
38
55
  # be registered as bot requests. Defaults to `true`.
56
+ # @param allow_ip_edits [Boolean] whether this client should allow non-GET
57
+ # requests if authentication hasn't been provided. Defaults to false. If
58
+ # this is set to true, the IP address of the device from which the
59
+ # request was sent will be credited for the edit. Make sure not to allow
60
+ # these edits if you don't want your IP address (and in many cases, a
61
+ # very close approximation of your physical location) exposed publicly.
39
62
  # @return [Wikidatum::Client]
40
- def initialize(user_agent:, wikibase_url: 'https://www.wikidata.org', bot: true)
63
+ def initialize(user_agent:, wikibase_url: 'https://www.wikidata.org', bot: true, allow_ip_edits: false)
41
64
  raise ArgumentError, "Wikibase URL must not end with a `/`, got #{wikibase_url.inspect}." if wikibase_url.end_with?('/')
42
65
 
43
- # TODO: Add the Ruby gem version to the UserAgent automatically, and
44
- # restrict the ability for end-users to actually set the UserAgent?
45
- @user_agent = user_agent
66
+ @user_agent = "Wikidatum Ruby gem v#{Wikidatum::VERSION}: #{user_agent}"
46
67
  @wikibase_url = wikibase_url
47
68
  @bot = bot
69
+ @allow_ip_edits = allow_ip_edits
48
70
 
49
71
  Faraday.default_adapter = :net_http
50
72
  end
@@ -97,7 +119,7 @@ module Wikidatum
97
119
  # wikidatum_client.add_statement(
98
120
  # id: 'Q123',
99
121
  # property: 'P23',
100
- # datavalue: Wikidatum::DataValueType::WikibaseString.new(string: 'Foo'),
122
+ # value: Wikidatum::DataType::WikibaseString.new(string: 'Foo'),
101
123
  # comment: 'Adding something or another.'
102
124
  # )
103
125
  #
@@ -105,7 +127,7 @@ module Wikidatum
105
127
  # wikidatum_client.add_statement(
106
128
  # id: 'Q123',
107
129
  # property: 'P124',
108
- # datavalue: Wikidatum::DataValueType::NoValue.new(
130
+ # value: Wikidatum::DataType::NoValue.new(
109
131
  # type: :no_value,
110
132
  # value: nil
111
133
  # )
@@ -115,7 +137,7 @@ module Wikidatum
115
137
  # wikidatum_client.add_statement(
116
138
  # id: 'Q123',
117
139
  # property: 'P124',
118
- # datavalue: Wikidatum::DataValueType::SomeValue.new(
140
+ # value: Wikidatum::DataType::SomeValue.new(
119
141
  # type: :some_value,
120
142
  # value: nil
121
143
  # )
@@ -125,7 +147,7 @@ module Wikidatum
125
147
  # wikidatum_client.add_statement(
126
148
  # id: 'Q123',
127
149
  # property: 'P124',
128
- # datavalue: Wikidatum::DataValueType::GlobeCoordinate.new(
150
+ # value: Wikidatum::DataType::GlobeCoordinate.new(
129
151
  # latitude: 52.51666,
130
152
  # longitude: 13.3833,
131
153
  # precision: 0.01666,
@@ -137,7 +159,7 @@ module Wikidatum
137
159
  # wikidatum_client.add_statement(
138
160
  # id: 'Q123',
139
161
  # property: 'P124',
140
- # datavalue: Wikidatum::DataValueType::MonolingualText.new(
162
+ # value: Wikidatum::DataType::MonolingualText.new(
141
163
  # language: 'en',
142
164
  # text: 'Foobar'
143
165
  # )
@@ -147,10 +169,8 @@ module Wikidatum
147
169
  # wikidatum_client.add_statement(
148
170
  # id: 'Q123',
149
171
  # property: 'P124',
150
- # datavalue: Wikidatum::DataValueType::Quantity.new(
172
+ # value: Wikidatum::DataType::Quantity.new(
151
173
  # amount: '+12',
152
- # upper_bound: nil,
153
- # lower_bound: nil,
154
174
  # unit: 'https://wikidata.org/entity/Q1234'
155
175
  # )
156
176
  # )
@@ -159,9 +179,8 @@ module Wikidatum
159
179
  # wikidatum_client.add_statement(
160
180
  # id: 'Q123',
161
181
  # property: 'P124',
162
- # datavalue: Wikidatum::DataValueType::Time.new(
182
+ # value: Wikidatum::DataType::Time.new(
163
183
  # time: '+2022-08-12T00:00:00Z',
164
- # time_zone: 0,
165
184
  # precision: 11,
166
185
  # calendar_model: 'https://wikidata.org/entity/Q1234'
167
186
  # )
@@ -171,66 +190,70 @@ module Wikidatum
171
190
  # wikidatum_client.add_statement(
172
191
  # id: 'Q123',
173
192
  # property: 'P124',
174
- # datavalue: Wikidatum::DataValueType::WikibaseEntityId.new(
175
- # entity_type: 'item',
176
- # numeric_id: 1234,
193
+ # value: Wikidatum::DataType::WikibaseItem.new(
177
194
  # id: 'Q1234'
178
195
  # )
179
196
  # )
180
197
  #
181
- # @param id [String] the ID of the item on which the statement will be added.
182
- # @param property [String] property ID in the format 'P123'.
183
- # @param datavalue [Wikidatum::DataValueType::GlobeCoordinate, Wikidatum::DataValueType::MonolingualText, Wikidatum::DataValueType::Quantity, Wikidatum::DataValueType::WikibaseString, Wikidatum::DataValueType::Time, Wikidatum::DataValueType::WikibaseEntityId, Wikidatum::DataValueType::NoValue, Wikidatum::DataValueType::SomeValue] the datavalue of the statement being created.
184
- # @param datatype [String, nil] if nil, it'll determine the type based on what was passed for the statement argument. This may differ from the type of the Statement's datavalue (for example with the 'url' type).
185
- # @param qualifiers [Hash<String, Array<Wikidatum::Snak>>]
198
+ # @param id [String, Integer] the ID of the item on which the statement will be added.
199
+ # @param property [String, Integer] property ID in the format 'P123', or an integer.
200
+ # @param value [Wikidatum::DataType::GlobeCoordinate, Wikidatum::DataType::MonolingualText, Wikidatum::DataType::Quantity, Wikidatum::DataType::WikibaseString, Wikidatum::DataType::Time, Wikidatum::DataType::WikibaseItem, Wikidatum::DataType::NoValue, Wikidatum::DataType::SomeValue] the value of the statement being created.
201
+ # @param qualifiers [Array<Wikidatum::Qualifier>]
186
202
  # @param references [Array<Wikidatum::Reference>]
187
- # @param rank [String]
203
+ # @param rank [String, Symbol] Valid ranks are 'preferred', 'normal', or
204
+ # 'deprecated'. Defaults to 'normal'. Also accepts Symbol for these ranks.
188
205
  # @param tags [Array<String>]
189
206
  # @param comment [String, nil]
190
207
  # @return [Boolean] True if the request succeeded.
191
- def add_statement(id:, property:, datavalue:, datatype: nil, qualifiers: {}, references: [], rank: 'normal', tags: [], comment: nil)
208
+ def add_statement(id:, property:, value:, qualifiers: [], references: [], rank: 'normal', tags: [], comment: nil)
192
209
  raise ArgumentError, "#{id.inspect} is an invalid Wikibase QID. Must be an integer, a string representation of an integer, or in the format 'Q123'." unless id.is_a?(Integer) || id.match?(ITEM_REGEX)
210
+ raise ArgumentError, "#{property.inspect} is an invalid Wikibase PID. Must be an integer, a string representation of an integer, or in the format 'P123'." unless property.is_a?(Integer) || property.match?(PROPERTY_REGEX)
211
+ raise ArgumentError, "#{rank.inspect} is an invalid rank. Must be normal, preferred, or deprecated." unless VALID_RANKS.include?(rank.to_s)
212
+ raise ArgumentError, "Expected an instance of one of Wikidatum::DataType's subclasses for value, but got #{value.inspect}." unless VALID_DATA_TYPES.include?(value.class.to_s)
193
213
 
194
214
  id = coerce_item_id(id)
215
+ property = coerce_property_id(property)
195
216
 
196
- # Unless datatype is set explicitly by the caller, just assume we can pull the
197
- # default from the datavalue class.
198
- datatype ||= datavalue.wikibase_datatype
199
-
200
- case datavalue.class.to_s
201
- when 'Wikidatum::DataValueType::NoValue'
217
+ case value.class.to_s
218
+ when 'Wikidatum::DataType::NoValue'
202
219
  statement_hash = {
203
- mainsnak: {
204
- snaktype: 'novalue',
205
- property: property,
206
- datatype: datatype
220
+ property: {
221
+ id: property
222
+ },
223
+ value: {
224
+ type: 'novalue'
207
225
  }
208
226
  }
209
- when 'Wikidatum::DataValueType::SomeValue'
227
+ when 'Wikidatum::DataType::SomeValue'
210
228
  statement_hash = {
211
- mainsnak: {
212
- snaktype: 'somevalue',
213
- property: property,
214
- datatype: datatype
229
+ property: {
230
+ id: property
231
+ },
232
+ value: {
233
+ type: 'somevalue'
215
234
  }
216
235
  }
217
- when 'Wikidatum::DataValueType::GlobeCoordinate', 'Wikidatum::DataValueType::MonolingualText', 'Wikidatum::DataValueType::Quantity', 'Wikidatum::DataValueType::WikibaseString', 'Wikidatum::DataValueType::Time', 'Wikidatum::DataValueType::WikibaseEntityId'
236
+ when 'Wikidatum::DataType::GlobeCoordinate', 'Wikidatum::DataType::MonolingualText', 'Wikidatum::DataType::Quantity', 'Wikidatum::DataType::WikibaseString', 'Wikidatum::DataType::Time', 'Wikidatum::DataType::WikibaseItem'
218
237
  statement_hash = {
219
- mainsnak: {
220
- snaktype: 'value',
221
- property: property,
222
- datatype: datatype,
223
- datavalue: {
224
- type: datavalue.wikibase_type,
225
- value: datavalue.marshal_dump
226
- }
238
+ property: {
239
+ id: property
240
+ },
241
+ value: {
242
+ type: 'value',
243
+ content: value.marshal_dump
227
244
  }
228
245
  }
229
- else
230
- raise ArgumentError, "Expected an instance of one of Wikidatum::DataValueType's subclasses for datavalue, but got #{datavalue.inspect}."
231
246
  end
232
247
 
233
- body = { statement: statement_hash.merge({ qualifiers: qualifiers, references: references, rank: rank, type: "statement" }) }
248
+ body = {
249
+ statement: statement_hash.merge(
250
+ {
251
+ qualifiers: qualifiers,
252
+ references: references,
253
+ rank: rank.to_s
254
+ }
255
+ )
256
+ }
234
257
 
235
258
  response = post_request("/entities/items/#{id}/statements", body, tags: tags, comment: comment)
236
259
 
@@ -261,6 +284,29 @@ module Wikidatum
261
284
  response.success?
262
285
  end
263
286
 
287
+ # Is the current instance of Client authenticated as a Wikibase user?
288
+ #
289
+ # @return [Boolean]
290
+ def authenticated?
291
+ # TODO: Make it possible for this to be true once authentication
292
+ # is implemented.
293
+ false
294
+ end
295
+
296
+ # Does the current instance of Client allow anonymous IP-based edits?
297
+ #
298
+ # @return [Boolean]
299
+ def allow_ip_edits?
300
+ @allow_ip_edits
301
+ end
302
+
303
+ # Is the current instance of Client editing as a bot?
304
+ #
305
+ # @return [Boolean]
306
+ def bot?
307
+ @bot
308
+ end
309
+
264
310
  private
265
311
 
266
312
  # For now this just returns the `@wikibase_url`, but in the future the API
@@ -309,7 +355,9 @@ module Wikidatum
309
355
  # @param tags [Array<String>] The tags to apply to the edit being made by this request, for PUT/POST/DELETE requests.
310
356
  # @param comment [String] The edit description, for PUT/POST/DELETE requests.
311
357
  # @return [Hash] JSON response, parsed into a hash.
312
- def post_request(path, body = {}, tags: nil, comment: nil)
358
+ def post_request(path, body = {}, tags: [], comment: nil)
359
+ ensure_edit_permitted!
360
+
313
361
  url = "#{api_url}#{path}"
314
362
 
315
363
  body[:bot] = @bot
@@ -323,6 +371,13 @@ module Wikidatum
323
371
 
324
372
  puts response.body.inspect if ENV['DEBUG']
325
373
 
374
+ # Error handling if it doesn't return a 200
375
+ unless response.success?
376
+ puts 'Something went wrong with this request!'
377
+ puts "Status Code: #{response.status}"
378
+ puts response.body.inspect
379
+ end
380
+
326
381
  response
327
382
  end
328
383
 
@@ -333,6 +388,8 @@ module Wikidatum
333
388
  # @param comment [String] The edit description, for PUT/POST/DELETE requests.
334
389
  # @return [Hash] JSON response, parsed into a hash.
335
390
  def delete_request(path, tags: [], comment: nil)
391
+ ensure_edit_permitted!
392
+
336
393
  url = "#{api_url}#{path}"
337
394
 
338
395
  body = {}
@@ -368,5 +425,31 @@ module Wikidatum
368
425
 
369
426
  "Q#{id}"
370
427
  end
428
+
429
+ # Coerce a Property ID in the formats 'P123', '123' or 123 into a consistent
430
+ # 'P123' format. We need to have the ID in the format 'P123' for the API
431
+ # request, which is why coercion is necessary.
432
+ #
433
+ # @param property_id [String, Integer]
434
+ # @return [String]
435
+ def coerce_property_id(property_id)
436
+ return property_id if property_id.to_s.start_with?('P')
437
+
438
+ "P#{property_id}"
439
+ end
440
+
441
+ # Check if authentication has been provided, and then check if IP edits
442
+ # are allowed. If neither condition returns true, raise an error.
443
+ #
444
+ # Also check if the user is performing IP edits as a bot, which will
445
+ # always return a 403 error from the REST API, and return a specific
446
+ # error message if so.
447
+ #
448
+ # @return [void]
449
+ # @raise [DisallowedIpEditError, DisallowedBotEditError]
450
+ def ensure_edit_permitted!
451
+ raise DisallowedIpEditError if !authenticated? && !allow_ip_edits?
452
+ raise DisallowedBotEditError if !authenticated? && bot?
453
+ end
371
454
  end
372
455
  end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ # For more information on the possible types that can be returned by
4
+ # datavalues, see the official documentation:
5
+ # https://doc.wikimedia.org/Wikibase/master/php/md_docs_topics_json.html#json_datavalues
6
+ module Wikidatum::DataType
7
+ class Base
8
+ # Represents the type for this instance.
9
+ #
10
+ # Possible values for the `type` attribute are:
11
+ #
12
+ # - `:no_value`: No value
13
+ # - `:some_value`: Unknown value
14
+ # - `:globe_coordinate`: {DataType::GlobeCoordinate}
15
+ # - `:monolingual_text`: {DataType::MonolingualText}
16
+ # - `:quantity`: {DataType::Quantity}
17
+ # - `:string`: {DataType::WikibaseString}
18
+ # - `:time`: {DataType::Time}
19
+ # - `:wikibase_item`: {DataType::WikibaseItem}
20
+ #
21
+ # @return [Symbol]
22
+ attr_reader :type
23
+
24
+ # The value of the "content" attribute in the response.
25
+ #
26
+ # If the `type` is `novalue` or `somevalue`, this returns `nil`.
27
+ #
28
+ # @return [DataType::GlobeCoordinate, DataType::MonolingualText, DataType::Quantity, DataType::WikibaseString, DataType::Time, DataType::WikibaseItem, nil]
29
+ attr_reader :content
30
+
31
+ # @param type [Symbol]
32
+ # @param content [DataType::GlobeCoordinate, DataType::MonolingualText, DataType::Quantity, DataType::WikibaseString, DataType::Time, DataType::WikibaseItem, nil] nil if type is no_value or some_value
33
+ # @return [void]
34
+ def initialize(type:, content:)
35
+ @type = type
36
+ @content = content
37
+ end
38
+
39
+ # @return [Hash]
40
+ def to_h
41
+ {
42
+ type: @type,
43
+ content: @content&.to_h
44
+ }
45
+ end
46
+
47
+ # @!visibility private
48
+ #
49
+ # @param data_type [String] The value of `data-type` for the given Statement or Qualifier's property.
50
+ # @param data_value_json [Hash] The `content` part of value object.
51
+ # @return [Wikidatum::DataType::Base] An instance of Base.
52
+ def self.marshal_load(data_type, data_value_json)
53
+ unless Wikidatum::DataType::DATA_TYPES.keys.include?(data_type.to_sym)
54
+ puts "WARNING: Unsupported data type (#{data_type})"
55
+ return nil
56
+ end
57
+
58
+ Object.const_get(Wikidatum::DataType::DATA_TYPES[data_type.to_sym]).marshal_load(data_value_json)
59
+ end
60
+ end
61
+ end
@@ -1,23 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'wikidatum/data_value_type/base'
3
+ require 'wikidatum/data_type/base'
4
4
 
5
- # The Globe Coordinate type datavalue JSON looks like this:
5
+ # The Globe Coordinate type JSON looks like this:
6
6
  #
7
7
  # ```json
8
8
  # {
9
- # "datavalue": {
10
- # "value": {
11
- # "latitude": 52.516666666667,
12
- # "longitude": 13.383333333333,
13
- # "precision": 0.016666666666667,
9
+ # "property": {
10
+ # "id": "P740",
11
+ # "data-type": "globe-coordinate"
12
+ # },
13
+ # "value": {
14
+ # "type": "value",
15
+ # "content": {
16
+ # "latitude": 38.8977,
17
+ # "longitude": -77.0365,
18
+ # "precision": 0.0001,
14
19
  # "globe": "http://www.wikidata.org/entity/Q2"
15
- # },
16
- # "type": "globecoordinate"
20
+ # }
17
21
  # }
18
22
  # }
19
23
  # ```
20
- class Wikidatum::DataValueType::GlobeCoordinate
24
+ class Wikidatum::DataType::GlobeCoordinate
21
25
  # @return [Float]
22
26
  attr_reader :latitude
23
27
 
@@ -56,22 +60,19 @@ class Wikidatum::DataValueType::GlobeCoordinate
56
60
  #
57
61
  # @return [String]
58
62
  def wikibase_type
59
- 'globecoordinate'
63
+ 'globe-coordinate'
60
64
  end
61
65
 
62
- # The "datatype" value used by Wikibase, usually identical to wikibase_type
63
- # but not always.
64
- #
65
- # @return [String]
66
- def wikibase_datatype
67
- 'globe-coordinate' # yes, really
66
+ # @return [Symbol]
67
+ def self.symbolized_name
68
+ :monolingual_text
68
69
  end
69
70
 
70
71
  # @!visibility private
71
72
  def self.marshal_load(data_value_json)
72
- Wikidatum::DataValueType::Base.new(
73
- type: :globe_coordinate,
74
- value: new(
73
+ Wikidatum::DataType::Base.new(
74
+ type: symbolized_name,
75
+ content: new(
75
76
  latitude: data_value_json['latitude'],
76
77
  longitude: data_value_json['longitude'],
77
78
  precision: data_value_json['precision'],
@@ -1,21 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'wikidatum/data_value_type/base'
3
+ require 'wikidatum/data_type/base'
4
4
 
5
- # The Monolingual Text type datavalue JSON looks like this:
5
+ # The Monolingual Text type JSON looks like this:
6
6
  #
7
7
  # ```json
8
8
  # {
9
- # "datavalue": {
10
- # "value": {
11
- # "text": "South Pole Telescope eyes birth of first massive galaxies",
12
- # "language": "en"
13
- # },
14
- # "type": "monolingualtext"
9
+ # "property": {
10
+ # "id": "P13432",
11
+ # "data-type": "monolingualtext"
12
+ # },
13
+ # "value": {
14
+ # "type": "value",
15
+ # "content": {
16
+ # "text": "foo",
17
+ # "language": "en-gb"
18
+ # }
15
19
  # }
16
20
  # }
17
21
  # ```
18
- class Wikidatum::DataValueType::MonolingualText
22
+ class Wikidatum::DataType::MonolingualText
19
23
  # @return [String] the language code, e.g. 'en'
20
24
  attr_reader :language
21
25
 
@@ -45,19 +49,16 @@ class Wikidatum::DataValueType::MonolingualText
45
49
  'monolingualtext'
46
50
  end
47
51
 
48
- # The "datatype" value used by Wikibase, usually identical to wikibase_type
49
- # but not always.
50
- #
51
- # @return [String]
52
- def wikibase_datatype
53
- wikibase_type
52
+ # @return [Symbol]
53
+ def self.symbolized_name
54
+ :monolingual_text
54
55
  end
55
56
 
56
57
  # @!visibility private
57
58
  def self.marshal_load(data_value_json)
58
- Wikidatum::DataValueType::Base.new(
59
- type: :monolingual_text,
60
- value: new(
59
+ Wikidatum::DataType::Base.new(
60
+ type: symbolized_name,
61
+ content: new(
61
62
  language: data_value_json['language'],
62
63
  text: data_value_json['text']
63
64
  )
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'wikidatum/data_value_type/base'
3
+ require 'wikidatum/data_type/base'
4
4
 
5
5
  # The NoValue type actually has no datavalue key in the blob at all. We work
6
6
  # around this by just passing nil to the serializer.
7
7
 
8
8
  # Represents "no value".
9
- class Wikidatum::DataValueType::NoValue < Wikidatum::DataValueType::Base
9
+ class Wikidatum::DataType::NoValue < Wikidatum::DataType::Base
10
10
  # The "type" value used by Wikibase, for use when creating/updating statements.
11
11
  #
12
12
  # @return [String]
@@ -14,16 +14,8 @@ class Wikidatum::DataValueType::NoValue < Wikidatum::DataValueType::Base
14
14
  'string'
15
15
  end
16
16
 
17
- # The "datatype" value used by Wikibase, usually identical to wikibase_type
18
- # but not always.
19
- #
20
- # @return [String]
21
- def wikibase_datatype
22
- wikibase_type
23
- end
24
-
25
17
  # @!visibility private
26
18
  def self.marshal_load(_data_value_json)
27
- new(type: :no_value, value: nil)
19
+ new(type: :no_value, content: nil)
28
20
  end
29
21
  end