wikidatum 0.2.1 → 0.3.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.
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