reality 0.0.3 → 0.0.4

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.
@@ -1,16 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
+
2
3
  require 'rubygems'
3
4
  require 'reality'
4
- require 'reality/pretty_inspect'
5
- require 'reality/shortcuts'
5
+ require 'reality/command_line'
6
6
 
7
- Reality.configure :demo
7
+ reality_runner = Reality::CommandLine.new
8
8
 
9
- class << self
10
- # including it ONLY into the main object, not Kernel
11
- include Reality::Methods
9
+ if reality_runner.interactive?
10
+ reality_runner.run_interactive_shell
11
+ else
12
+ puts reality_runner.results
12
13
  end
13
-
14
- require 'irb'
15
- ARGV.shift until ARGV.empty?
16
- IRB.start
@@ -1,3 +1,4 @@
1
1
  keys:
2
2
  open_weather_map: '90d73c1188829195d023b5a5fc6399e1'
3
3
  geonames: 'realitygeo'
4
+ quandl: JU6KEPEkqqqfVkcpa9MU
@@ -1,7 +1,14 @@
1
1
  require 'infoboxer'
2
2
  require 'yaml'
3
3
 
4
+ # Reality is library for accessing all world data, starting from Wikipedia.
5
+ #
6
+ # Look at {Entity} for good starting point.
7
+ #
8
+ # You also may want to navigate [Getting started](https://github.com/molybdenum-99/reality/wiki/Getting-started)
9
+ # page in our wiki.
4
10
  module Reality
11
+ # @private
5
12
  def self.require_(*modules)
6
13
  modules.flatten.flat_map{|pattern|
7
14
  Dir[File.expand_path("../reality/#{pattern}.rb", __FILE__)]
@@ -19,16 +26,14 @@ module Reality
19
26
  # entities
20
27
  require_ %w[entity list]
21
28
  require_ %w[definitions/*]
22
- require_ %w[methods]
29
+ require_ %w[methods names]
23
30
 
31
+ include Methods
24
32
  extend Methods
25
33
 
26
- def self.reload!
27
- require_ %w[definitions/*]
28
- end
29
-
30
34
  # extras
31
- require_ %w[extras/open_weather_map extras/geonames]
35
+ require_ %w[extras/open_weather_map extras/geonames extras/quandl]
32
36
  include Extras::OpenWeatherMap
33
37
  include Extras::Geonames
38
+ include Extras::Quandl
34
39
  end
@@ -0,0 +1,124 @@
1
+ require 'optparse'
2
+ require 'reality/pretty_inspect'
3
+
4
+ module Reality
5
+ # This module contains services used from `bin/reality`, you typically
6
+ # don't need to think of it.
7
+ class CommandLine
8
+ attr_accessor :search_term, :article, :commands, :options, :errors
9
+
10
+ def initialize
11
+ parse_arguments
12
+ end
13
+
14
+ def self.display_usage
15
+ puts "usage: reality \"[search-string]\" [entity-command] [chained-command(s) ...]"
16
+ end
17
+
18
+ def interactive?
19
+ !!self.options[:interactive]
20
+ end
21
+
22
+ def article_found?
23
+ !self.article.nil?
24
+ end
25
+
26
+ def subcommand_for(object, subcommand)
27
+ if object.respond_to?(subcommand.to_sym)
28
+ puts "Calling #{subcommand} on #{object.inspect}" if ENV['DEBUG']
29
+ object.send(subcommand.to_sym)
30
+ else
31
+ self.errors << "#{object} doesn't respond to #{subcommand}"
32
+ nil
33
+ end
34
+ end
35
+
36
+ def results
37
+ return "Nothing found for: #{self.search_term}" unless self.article_found?
38
+ puts "Attempting entity chain: #{self.commands} on #{self.article.inspect}" if ENV['DEBUG']
39
+
40
+ result = subcommand_for(self.article, self.commands.shift)
41
+
42
+ while subcommand = self.commands.shift
43
+ result = subcommand_for(result, subcommand)
44
+ end
45
+
46
+ if self.errors.any?
47
+ "Error: #{ self.errors.join("\n") }"
48
+ else
49
+ result
50
+ end
51
+ end
52
+
53
+ def run_interactive_shell
54
+ require 'irb'
55
+ require 'reality/shortcuts'
56
+ ::ARGV.clear
57
+
58
+ # FIXME: can't see better means to have everything accessible & included
59
+ #IRB::ExtendCommandBundle.include(Reality)
60
+ TOPLEVEL_BINDING.receiver.send(:include, Reality)
61
+
62
+ IRB.setup nil
63
+
64
+ IRB.conf[:IRB_NAME] = 'reality'
65
+
66
+ IRB.conf[:PROMPT] = {}
67
+ IRB.conf[:PROMPT][:REALITY] = {
68
+ :PROMPT_I => '%N:%03n:%i> ',
69
+ :PROMPT_S => '%N:%03n:%i%l ',
70
+ :PROMPT_C => '%N:%03n:%i* ',
71
+ :RETURN => "# => %s\n"
72
+ }
73
+ IRB.conf[:PROMPT_MODE] = :REALITY
74
+ IRB.conf[:RC] = false
75
+
76
+ IRB.conf[:MAIN_CONTEXT] = IRB::Irb.new.context
77
+
78
+ require 'irb/ext/multi-irb'
79
+ IRB.irb nil, TOPLEVEL_BINDING
80
+ end
81
+
82
+ private
83
+
84
+ def parse_options
85
+ self.options = {}
86
+
87
+ OptionParser.new do |opts|
88
+ opts.banner = "Usage: reality [options] [search-string] [entity-command] [chained-command(s) ...]"
89
+
90
+ opts.on_tail("-i", "--interactive", "Run an interactive IRB session with Reality pre-configured for querying.") do
91
+ self.options[:interactive] = true
92
+ end
93
+
94
+ opts.on_tail("-h", "--help", "Show this message") do
95
+ puts opts
96
+ exit
97
+ end
98
+ end.parse!
99
+ end
100
+
101
+ def parse_arguments
102
+ parse_options
103
+ self.search_term = "#{::ARGV.shift}"
104
+
105
+ if self.options[:interactive]
106
+ Reality.configure :demo
107
+ elsif self.search_term.length > 0
108
+ self.article = Reality::Entity(self.search_term)
109
+ self.errors = []
110
+
111
+ if ::ARGV.count > 0
112
+ self.commands = ::ARGV.map(&:to_sym)
113
+ else
114
+ self.commands = [:describe]
115
+ end
116
+
117
+ Reality.configure :demo
118
+ else
119
+ self.class.display_usage
120
+ exit
121
+ end
122
+ end
123
+ end
124
+ end
@@ -32,15 +32,22 @@ module Reality
32
32
  end
33
33
  end
34
34
 
35
+ # @private
35
36
  def Reality.config
36
37
  @config ||= Config.new
37
38
  end
38
39
 
39
- def Reality.configure(cfg)
40
- if cfg == :demo
40
+ # Allows to configure Reality.
41
+ #
42
+ # @param path [String] Path to config. See `config/demo.yml` for config
43
+ # sample. Also, you can use `:demo` value for config Reality with
44
+ # demo keys.
45
+ #
46
+ def Reality.configure(path)
47
+ if path == :demo
41
48
  config.load(File.expand_path('../../../config/demo.yml', __FILE__))
42
49
  else
43
- config.load(cfg)
50
+ config.load(path)
44
51
  end
45
52
  end
46
53
  end
@@ -1,6 +1,7 @@
1
1
  require 'time_boots'
2
2
 
3
3
  module Reality
4
+ # @private
4
5
  # Just assorted "cool things", included into all entities
5
6
  # Subject to change/refactor
6
7
  module Helpers
@@ -9,6 +9,7 @@ module Reality
9
9
  predicate 'P571', :created_at, :date # TODO: aliases: :founded_at, :incepted_at
10
10
 
11
11
  predicate 'P740', :location, :entity
12
+ predicate 'P585', :date , :date # TODO: maybe :datetime?
12
13
 
13
14
  predicate 'P737', :influenced_by, [:entity]
14
15
 
@@ -30,13 +31,17 @@ module Reality
30
31
  predicate 'P2046', :area, :measure, unit: 'km²'
31
32
  predicate 'P2044', :elevation, :measure, unit: 'm'
32
33
 
33
- # Economy and socilogy ---------------------------------------------
34
+ predicate 'P969', :street_address, :string
35
+ predicate 'P131', :located_in, :entity
36
+
37
+ # Economy and sociology ---------------------------------------------
34
38
  predicate 'P38', :currency, :entity
35
39
  predicate 'P463', :organizations, [:entity]
36
40
  predicate 'P2131', :gdp_nominal, :measure, unit: '$'
37
41
  predicate 'P1082',:population, :measure, unit: 'person'
38
42
 
39
43
  predicate 'P35', :head_of_state, :entity
44
+ predicate 'P6', :head_of_government, :entity
40
45
 
41
46
  # References -------------------------------------------------------
42
47
  predicate 'P297', :iso2_code, :string
@@ -101,5 +106,9 @@ module Reality
101
106
  # Fictional entities -----------------------------------------------
102
107
  predicate 'P1080', :fictional_universe, :string
103
108
  predicate 'P1441', :present_in_works, [:entity]
109
+
110
+ # Internet ---------------------------------------------------------
111
+ predicate 'P856', :official_website, :string
112
+ predicate 'P2002', :twitter_username, :string
104
113
  end
105
114
  end
@@ -1,4 +1,5 @@
1
1
  module Reality
2
+ # @private
2
3
  module Character
3
4
  extend Entity::WikipediaType
4
5
 
@@ -1,4 +1,5 @@
1
1
  module Reality
2
+ # @private
2
3
  module City
3
4
  extend Entity::WikipediaType
4
5
 
@@ -1,4 +1,5 @@
1
1
  module Reality
2
+ # @private
2
3
  module Continent
3
4
  extend Entity::WikipediaType
4
5
 
@@ -1,4 +1,5 @@
1
1
  module Reality
2
+ # @private
2
3
  module Country
3
4
  extend Entity::WikipediaType
4
5
 
@@ -1,4 +1,5 @@
1
1
  module Reality
2
+ # @private
2
3
  module MusicalArtist
3
4
  extend Entity::WikipediaType
4
5
 
@@ -1,4 +1,5 @@
1
1
  module Reality
2
+ # @private
2
3
  module Person
3
4
  extend Entity::WikipediaType
4
5
 
@@ -1,25 +1,120 @@
1
1
  module Reality
2
2
  require_ %w[entity/coercion entity/wikidata_predicates entity/wikipedia_type]
3
-
3
+
4
+ # Reality::Entity is a main concept of the library. It represents errr
5
+ # well, some entity from real world. You can think of it as of rough
6
+ # equivalent of Wikipedia article.
7
+ #
8
+ # Wiki has more details about entity [concept](https://github.com/molybdenum-99/reality/wiki/Entity)
9
+ # and [internals](https://github.com/molybdenum-99/reality/wiki/Entity%20internals).
10
+ #
11
+ # The easiest way to have an entity is to instantiate is as {Entity.load}
12
+ # (also aliased as `Reality.Entity()` method): you'll just have your
13
+ # entity already _loaded_ from all possible data sources (or `nil` if
14
+ # neither of them knows about it):
15
+ #
16
+ # ```ruby
17
+ # argentina = Reality::Entity('Argentina')
18
+ # # => #<Reality::Entity(Argentina):country>
19
+ # ```
20
+ # Then, you can use {#describe} to see what properties entity has, and
21
+ # call any of them by name, like `argentina.capital`.
22
+ #
23
+ # Or you can create not loaded entities with just {#initialize} (it
24
+ # may be useful when you want to further batch-load several of them
25
+ # through {List#load!}).
26
+ #
4
27
  class Entity
5
28
  using Refinements
6
-
7
- attr_reader :wikipage, :wikidata, :wikidata_id
8
- attr_reader :values, :wikipedia_type
9
-
10
- def initialize(name, wikipage: nil, wikidata: nil, wikidata_id: nil, load: false)
29
+
30
+ # Instance of Infoboxer's [page](http://www.rubydoc.info/gems/infoboxer/Infoboxer/MediaWiki/Page).
31
+ #
32
+ # Pretty useful on its own:
33
+ #
34
+ # ```ruby
35
+ # puts Reality::Entity('Argentina').wikipage.intro
36
+ # # Argentina (ˌɑrdʒənˈtiːnə; aɾxenˈtina), officially the Argentine Republic (República Argentina), is a federal republic....
37
+ # ```
38
+ #
39
+ # Refer to [Infoboxer's documentation](http://www.rubydoc.info/gems/infoboxer/Infoboxer/MediaWiki/Page)
40
+ # for details.
41
+ #
42
+ # @return [Infoboxer::MediaWiki::Page]
43
+ attr_reader :wikipage
44
+
45
+ # All values extracted from data sources, in structured form.
46
+ # You can pretty-previes them via {#describe}, as well as work with
47
+ # separate values with method call (see {#method_missing}).
48
+ #
49
+ # @return [Hash<Symbol, Object>]
50
+ attr_reader :values
51
+
52
+ # @private
53
+ attr_reader :wikipedia_type, :wikidata, :wikidata_id
54
+
55
+ # Creates new entity. Initially, entity is _not_ loaded from datasources,
56
+ # it's just a name. If you want to receive a loaded entity with one
57
+ # statement, take a look at {Entity.load}, which does `new` + `load!`
58
+ # under the hoods.
59
+ #
60
+ # ```
61
+ # e = Reality::Entity.new('Mississippi')
62
+ # # => #<Reality::Entity?(Mississippi)>
63
+ # e.loaded?
64
+ # # => false
65
+ # e.values
66
+ # # => {}
67
+ # ```
68
+ #
69
+ # @param name [String] Name of the entity you want. Basically, it's
70
+ # Wikipedia page name for some concept. Not-so-basically, please
71
+ # refer to [names explanation](https://github.com/molybdenum-99/reality/wiki/Entity#entity-names)
72
+ # in our wiki.
73
+ # @param wikidata_id [String] Used mostly internally (when not only
74
+ # entity name, but also wikidata id is known; this happens on loading
75
+ # entities by references from other entities).
76
+ def initialize(name, wikidata_id: nil)
11
77
  @name = name
12
- @wikipage, @wikidata, @wikidata_id = wikipage, wikidata, wikidata_id
78
+ @wikidata_id = wikidata_id
13
79
  @values = {}
14
-
15
- load! if load
16
- after_load if @wikipage
17
80
  end
18
81
 
82
+ # Entity name string. For not loaded entity returns the name by which it
83
+ # was created. For loaded, it's correct name of Wikipedia page:
84
+ #
85
+ # ```ruby
86
+ # e = Reality::Entity.new('Einstein')
87
+ # # => #<Reality::Entity?(Einstein)>
88
+ # e.name
89
+ # # => "Einstein"
90
+ # e.load!
91
+ # # => #<Reality::Entity(Albert Einstein)>
92
+ # e.name
93
+ # # => "Albert Einstein"
94
+ # ```
95
+ #
96
+ # @return [String]
19
97
  def name
20
98
  @wikipage ? @wikipage.title : @name
21
99
  end
22
100
 
101
+ # Returns entity brief representation. Things to note:
102
+ #
103
+ # ```
104
+ # #<Reality::Entity?(Argentina)>
105
+ # ^ ^
106
+ # | Entity name
107
+ # Sign of not
108
+ # loaded entity
109
+ #
110
+ # #<Reality::Entity(Argentina):country>
111
+ # ^ ^
112
+ # | Name of "additional type" (to be documented...)
113
+ # No question mark:
114
+ # entity is loaded
115
+ # ```
116
+ #
117
+ # @return [String]
23
118
  def inspect
24
119
  if @wikipedia_type && @wikipedia_type.symbol
25
120
  "#<#{self.class}#{loaded? ? '' : '?'}(#{name}):#{@wikipedia_type.symbol}>"
@@ -28,11 +123,27 @@ module Reality
28
123
  end
29
124
  end
30
125
 
31
- def _describe
32
- load! unless loaded?
33
- Util::Format.describe(inspect, values.map{|k,v| [k, v.inspect]})
34
- end
35
-
126
+ # Prints general object state and all properties with values
127
+ #
128
+ # Example:
129
+ #
130
+ # ```
131
+ # $> Reality::Entity.new('Mississippi').describe
132
+ # Output:
133
+ # -------------------------------
134
+ # <Reality::Entity(Mississippi)>
135
+ # -------------------------------
136
+ # capital: #<Reality::Entity?(Jackson)>
137
+ # coord: #<Reality::Geo::Coord(33°0′0″N,90°0′0″W)>
138
+ # country: #<Reality::Entity?(United States of America)>
139
+ # created_at: Wed, 10 Dec 1817
140
+ # located_in: #<Reality::Entity?(United States of America)>
141
+ # neighbours: #<Reality::List[Alabama?, Tennessee?, Louisiana?, Arkansas?]>
142
+ # official_website: "http://www.mississippi.gov"
143
+ # tz_offset: #<Reality::TZOffset(UTC-06:00)>
144
+ # ```
145
+ #
146
+ # @return [nil]
36
147
  def describe
37
148
  puts _describe
38
149
  nil
@@ -42,39 +153,70 @@ module Reality
42
153
  name
43
154
  end
44
155
 
156
+ # @private
45
157
  def to_s?
46
158
  # FIXME: fuuuuuuuu
47
159
  "#{name.include?(',') ? '"' + name + '"' : name}#{loaded? ? '' : '?'}"
48
160
  end
49
161
 
162
+ # Loads entity data from all external sources.
163
+ #
164
+ # Note that this method is called implicitly on {#method_missing},
165
+ # {#describe} or {#to_h}.
166
+ #
167
+ # Note also that if you need several entities to be loaded, its much
168
+ # more effective to have them grouped into {List} and batch-loaded
169
+ # via {List#load!}.
170
+ #
171
+ # @return [self]
50
172
  def load!
51
173
  if @wikidata_id
52
- @wikidata = Wikidata::Entity.fetch_by_id(@wikidata_id)
174
+ @wikidata = Wikidata::Entity.one_by_id(@wikidata_id)
53
175
  if @wikidata && @wikidata.en_wikipage
54
176
  @wikipage = Infoboxer.wikipedia.get(@wikidata.en_wikipage)
55
177
  end
56
178
  else
57
179
  @wikipage = Infoboxer.wikipedia.get(name)
58
- if @wikipage
59
- @wikidata = Wikidata::Entity.fetch(@wikipage.title).first
180
+ @wikidata = if @wikipage
181
+ Wikidata::Entity.one_by_wikititle(@wikipage.title)
182
+ else
183
+ Wikidata::Entity.one_by_label(name)
60
184
  end
61
185
  end
62
186
  after_load
63
187
  self
64
188
  end
65
189
 
190
+ # @private
66
191
  def setup!(wikipage: nil, wikidata: nil)
67
192
  @wikipage, @wikidata = wikipage, wikidata
68
- after_load if @wikipage
193
+ after_load if @wikipage || @wikidata
194
+ self
69
195
  end
70
196
 
197
+ # Returns `true` if entity is loaded already.
198
+ #
199
+ # @return [Boolean]
71
200
  def loaded?
72
- !!@wikipage
201
+ !!(@wikipage || @wikidata)
73
202
  end
74
203
 
204
+ # @private
75
205
  # Don't try to convert me!
76
206
  UNSUPPORTED_METHODS = [:to_hash, :to_ary, :to_a, :to_str, :to_int]
77
207
 
208
+ # Entity handles `method_missing` this way:
209
+ #
210
+ # * loads itself if it was not loaded;
211
+ # * returns one of {values} by method name.
212
+ #
213
+ # Note, that even if there's no value with required key, `method_missing`
214
+ # will return `nil` (and not through `NoMethodError` as someone may
215
+ # expect). That's because even supposedly homogenous entities may have different
216
+ # property sets, and typically you want to do something like
217
+ # `cities.map(&:area).compact.inject(:+)`, not handling exceptions
218
+ # about "this city has no 'area' property".
219
+ #
78
220
  def method_missing(sym, *arg, **opts, &block)
79
221
  if arg.empty? && opts.empty? && !block && sym !~ /[=?!]/ &&
80
222
  !UNSUPPORTED_METHODS.include?(sym)
@@ -92,28 +234,87 @@ module Reality
92
234
  end
93
235
  end
94
236
 
95
- def respond_to?(sym)
96
- sym !~ /[=?!]/ && !UNSUPPORTED_METHODS.include?(sym) || super
237
+ # @private
238
+ def respond_to?(sym, include_all = false)
239
+ sym !~ /[=?!]/ && !UNSUPPORTED_METHODS.include?(sym) || super(sym)
97
240
  end
98
241
 
99
242
  class << self
100
- def load(name, type = nil)
101
- Entity.new(name, load: true).tap{|entity|
102
- return nil if entity.instance_variable_get('@wikipage').nil?
103
- return nil if type && entity.wikipedia_type != type
243
+ # Loads Entity from all datasources. Returns either loaded entity
244
+ # or `nil` if entity not found.
245
+ #
246
+ # @param name [String] See {#initialize} for explanations about
247
+ # entity names.
248
+ #
249
+ # @return [Entity, nil]
250
+ def load(name)
251
+ Entity.new(name).load!.tap{|entity|
252
+ return nil if !entity.loaded?
104
253
  }
105
254
  end
106
255
  end
107
256
 
108
- #def to_h
109
- #if respond_to?(:properties)
110
- #properties.map{|sym|
111
- #[sym, to_simple_type(self.send(sym))]
112
- #}.to_h
113
- #else
114
- #{}
115
- #end
116
- #end
257
+ # Converts Entity to hash, preserving only _core types_ (so, you can
258
+ # store this hash in YAML or JSON, for example). Some notes on conversion:
259
+ # * Entity name goes to `:name` key;
260
+ # * Rational values became floating point;
261
+ # * {Measure} and {Geo::Coord} became hashes;
262
+ # * other entities became: when loaded - hashes, when not loaded -
263
+ # just strings of entity name
264
+ #
265
+ # Example:
266
+ #
267
+ # ```ruby
268
+ # argentina = Reality::Entity('Argentina')
269
+ # # => #<Reality::Entity(Argentina):country>
270
+ # argentina.head_of_government.load!
271
+ # # => #<Reality::Entity(Mauricio Macri)>
272
+ # agentina.to_h
273
+ # # {:name=>"Argentina",
274
+ # # :long_name=>"Argentine Republic",
275
+ # # :area=>{:amount=>2780400.0, :unit=>"km²"},
276
+ # # :gdp_ppp=>{:amount=>964279000000.0, :unit=>"$"},
277
+ # # :population=>{:amount=>43417000.0, :unit=>"person"},
278
+ # # :head_of_government=>
279
+ # # {:name=>"Mauricio Macri",
280
+ # # :birthday=>"1959-02-08",
281
+ # # ....},
282
+ # # :country=>"Argentina",
283
+ # # :continent=>"South America",
284
+ # # :head_of_state=>"Mauricio Macri",
285
+ # # :capital=>"Buenos Aires",
286
+ # # :currency=>"peso",
287
+ # # :neighbours=>["Uruguay", "Brazil", "Chile", "Paraguay", "Bolivia"],
288
+ # # :tld=>".ar",
289
+ # # :adm_divisions=>["Buenos Aires", "Buenos Aires Province", ....],
290
+ # # :iso2_code=>"AR",
291
+ # # :iso3_code=>"ARG",
292
+ # # :part_of=>["Latin America"],
293
+ # # :tz_offset=>"-03:00",
294
+ # # :organizations=>["United Nations","Union of South American Nations","Mercosur",...],
295
+ # # :calling_code=>"+54",
296
+ # # :created_at=>"1816-01-01",
297
+ # # :highest_point=>"Aconcagua",
298
+ # # :coord=>{:lat=>-34.0, :lng=>-64.0},
299
+ # # :official_website=>"http://www.argentina.gob.ar/",
300
+ # # :gdp_nominal=>{:amount=>537659972702.0, :unit=>"$"}}
301
+ # #
302
+ # ```
303
+ #
304
+ # @return [Hash]
305
+ def to_h
306
+ load! unless loaded?
307
+ {name: name}.merge \
308
+ values.map{|k, v| [k.to_sym, Coercion.to_simple_type(v)]}.to_h
309
+ end
310
+
311
+ # Converts entity to JSON (same as `entity.to_h.to_json`)
312
+ #
313
+ # @see #to_h
314
+ # @return [String]
315
+ def to_json
316
+ to_h.to_json
317
+ end
117
318
 
118
319
  protected
119
320
 
@@ -131,22 +332,9 @@ module Reality
131
332
  end
132
333
  end
133
334
 
134
- def to_simple_type(val)
135
- case val
136
- when nil, Numeric, String, Symbol
137
- val
138
- when Array
139
- val.map{|v| to_simple_type(v)}
140
- when Hash
141
- val.map{|k, v| [to_simple_type(k), to_simple_type(v)]}.to_h
142
- when Entity
143
- val.to_s
144
- when Reality::Measure
145
- val.amount.to_i
146
- else
147
- fail ArgumentError, "Non-coercible value #{val.class}"
148
- end
335
+ def _describe
336
+ load! unless loaded?
337
+ Util::Format.describe(inspect, values.map{|k,v| [k, v.inspect]})
149
338
  end
150
-
151
339
  end
152
340
  end