Class: Reality::Entity

Inherits:
Object
  • Object
show all
Defined in:
lib/reality/entity.rb,
lib/reality/entity/coercion.rb,
lib/reality/entity/wikipedia_type.rb,
lib/reality/entity/wikidata_predicates.rb

Overview

Reality::Entity is a main concept of the library. It represents errr well, some entity from real world. You can think of it as of rough equivalent of Wikipedia article.

Wiki has more details about entity concept and internals.

The easiest way to have an entity is to instantiate is as Entity.load (also aliased as Reality.Entity() method): you'll just have your entity already loaded from all possible data sources (or nil if neither of them knows about it):

argentina = Reality::Entity('Argentina')
# => #<Reality::Entity(Argentina):country>

Then, you can use #describe to see what properties entity has, and call any of them by name, like argentina.capital.

Or you can create not loaded entities with just #initialize (it may be useful when you want to further batch-load several of them through List#load!).

Defined Under Namespace

Modules: Coercion

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, wikidata_id: nil) ⇒ Entity

Creates new entity. Initially, entity is not loaded from datasources, it's just a name. If you want to receive a loaded entity with one statement, take a look at load, which does new + load! under the hoods.

e = Reality::Entity.new('Mississippi')
# => #<Reality::Entity?(Mississippi)>
e.loaded?
# => false
e.values
# => {}

Parameters:

  • name (String)

    Name of the entity you want. Basically, it's Wikipedia page name for some concept. Not-so-basically, please refer to names explanation in our wiki.

  • wikidata_id (String) (defaults to: nil)

    Used mostly internally (when not only entity name, but also wikidata id is known; this happens on loading entities by references from other entities).



77
78
79
80
81
# File 'lib/reality/entity.rb', line 77

def initialize(name, wikidata_id: nil)
  @name = name
  @wikidata_id = wikidata_id
  @values = {}
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *arg, **opts, &block) ⇒ Object

Entity handles method_missing this way:

  • loads itself if it was not loaded;
  • returns one of #values by method name.

Note, that even if there's no value with required key, method_missing will return nil (and not through NoMethodError as someone may expect). That's because even supposedly homogenous entities may have different property sets, and typically you want to do something like cities.map(&:area).compact.inject(:+), not handling exceptions about "this city has no 'area' property".



221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/reality/entity.rb', line 221

def method_missing(sym, *arg, **opts, &block)
  if arg.empty? && opts.empty? && !block && sym !~ /[=?!]/ &&
    !UNSUPPORTED_METHODS.include?(sym)

    load! unless loaded?

    # now some new method COULD emerge while loading
    if methods.include?(sym)
      send(sym)
    else
      values[sym]
    end
  else
    super
  end
end

Instance Attribute Details

#valuesHash<Symbol, Object> (readonly) Also known as: attributes

All values extracted from data sources, in structured form. You can pretty-previes them via #describe, as well as work with separate values with method call (see #method_missing).

Returns:

  • (Hash<Symbol, Object>)


50
51
52
# File 'lib/reality/entity.rb', line 50

def values
  @values
end

#wikipageInfoboxer::MediaWiki::Page (readonly)

Instance of Infoboxer's page.

Pretty useful on its own:

puts Reality::Entity('Argentina').wikipage.intro
# Argentina (ˌɑrdʒənˈtiːnə; aɾxenˈtina), officially the Argentine Republic (República Argentina), is a federal republic....

Refer to Infoboxer's documentation for details.

Returns:

  • (Infoboxer::MediaWiki::Page)


43
44
45
# File 'lib/reality/entity.rb', line 43

def wikipage
  @wikipage
end

Class Method Details

.load(name) ⇒ Entity?

Loads Entity from all datasources. Returns either loaded entity or nil if entity not found.

Parameters:

  • name (String)

    See #initialize for explanations about entity names.

Returns:



251
252
253
254
255
# File 'lib/reality/entity.rb', line 251

def load(name)
  Entity.new(name).load!.tap{|entity|
    return nil if !entity.loaded?
  }
end

Instance Method Details

#describenil

Prints general object state and all properties with values

Example:

$> Reality::Entity.new('Mississippi').describe
  Output:
  -------------------------------
  <Reality::Entity(Mississippi)>
  -------------------------------
         capital: #<Reality::Entity?(Jackson)>
           coord: #<Reality::Geo::Coord(33°0′0″N,90°0′0″W)>
         country: #<Reality::Entity?(United States of America)>
      created_at: Wed, 10 Dec 1817
      located_in: #<Reality::Entity?(United States of America)>
      neighbours: #<Reality::List[Alabama?, Tennessee?, Louisiana?, Arkansas?]>
official_website: "http://www.mississippi.gov"
       tz_offset: #<Reality::TZOffset(UTC-06:00)>

Returns:

  • (nil)


148
149
150
151
# File 'lib/reality/entity.rb', line 148

def describe
  puts _describe
  nil
end

#inspectString

Returns entity brief representation. Things to note:

#<Reality::Entity?(Argentina)>
                 ^    ^
                 |  Entity name
            Sign of not
            loaded entity

#<Reality::Entity(Argentina):country>
                 ^             ^
                 |           Name of "additional type" (to be documented...)
           No question mark:
           entity is loaded

Returns:

  • (String)


119
120
121
122
123
124
125
# File 'lib/reality/entity.rb', line 119

def inspect
  if @wikipedia_type && @wikipedia_type.symbol
    "#<#{self.class}#{loaded? ? '' : '?'}(#{name}):#{@wikipedia_type.symbol}>"
  else
    "#<#{self.class}#{loaded? ? '' : '?'}(#{name})>"
  end
end

#load!self

Loads entity data from all external sources.

Note that this method is called implicitly on #method_missing, #describe or #to_h.

Note also that if you need several entities to be loaded, its much more effective to have them grouped into List and batch-loaded via List#load!.

Returns:

  • (self)


173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/reality/entity.rb', line 173

def load!
  if @wikidata_id
    @wikidata = Wikidata::Entity.one_by_id(@wikidata_id)
    if @wikidata && @wikidata.en_wikipage
      @wikipage = Infoboxer.wikipedia.get(@wikidata.en_wikipage.tr('_', ' '))
    end
  else
    @wikipage = Infoboxer.wikipedia.get(name)
    @wikidata = if @wikipage
      Wikidata::Entity.one_by_wikititle(@wikipage.title)
    else
      Wikidata::Entity.one_by_label(name)
    end
  end
  after_load
  self
end

#loaded?Boolean

Returns true if entity is loaded already.

Returns:

  • (Boolean)


201
202
203
# File 'lib/reality/entity.rb', line 201

def loaded?
  !!(@wikipage || @wikidata)
end

#nameString

Entity name string. For not loaded entity returns the name by which it was created. For loaded, it's correct name of Wikipedia page:

e = Reality::Entity.new('Einstein')
# => #<Reality::Entity?(Einstein)>
e.name
# => "Einstein"
e.load!
# => #<Reality::Entity(Albert Einstein)>
e.name
# => "Albert Einstein"

Returns:

  • (String)


98
99
100
# File 'lib/reality/entity.rb', line 98

def name
  @wikipage ? @wikipage.title : @name
end

#to_hHash

Converts Entity to hash, preserving only core types (so, you can store this hash in YAML or JSON, for example). Some notes on conversion:

  • Entity name goes to :name key;
  • Rational values became floating point;
  • Measure and Geo::Coord became hashes;
  • other entities became: when loaded - hashes, when not loaded - just strings of entity name

Example:

argentina = Reality::Entity('Argentina')
# => #<Reality::Entity(Argentina):country>
argentina.head_of_government.load!
# => #<Reality::Entity(Mauricio Macri)>
agentina.to_h
# {:name=>"Argentina",
# :long_name=>"Argentine Republic",
# :area=>{:amount=>2780400.0, :unit=>"km²"},
# :gdp_ppp=>{:amount=>964279000000.0, :unit=>"$"},
# :population=>{:amount=>43417000.0, :unit=>"person"},
# :head_of_government=>
#   {:name=>"Mauricio Macri",
#   :birthday=>"1959-02-08",
#   ....},
# :country=>"Argentina",
# :continent=>"South America",
# :head_of_state=>"Mauricio Macri",
# :capital=>"Buenos Aires",
# :currency=>"peso",
# :neighbours=>["Uruguay", "Brazil", "Chile", "Paraguay", "Bolivia"],
# :tld=>".ar",
# :adm_divisions=>["Buenos Aires", "Buenos Aires Province", ....],
# :iso2_code=>"AR",
# :iso3_code=>"ARG",
# :part_of=>["Latin America"],
# :tz_offset=>"-03:00",
# :organizations=>["United Nations","Union of South American Nations","Mercosur",...],
# :calling_code=>"+54",
# :created_at=>"1816-01-01",
# :highest_point=>"Aconcagua",
# :coord=>{:lat=>-34.0, :lng=>-64.0},
# :official_website=>"http://www.argentina.gob.ar/",
# :gdp_nominal=>{:amount=>537659972702.0, :unit=>"$"}}
#

Returns:

  • (Hash)


306
307
308
309
310
# File 'lib/reality/entity.rb', line 306

def to_h
  load! unless loaded?
  {name: name}.merge \
    values.map{|k, v| [k.to_sym, Coercion.to_simple_type(v)]}.to_h
end

#to_jsonString

Converts entity to JSON (same as entity.to_h.to_json)

Returns:

  • (String)

See Also:



316
317
318
# File 'lib/reality/entity.rb', line 316

def to_json
  to_h.to_json
end

#to_sObject



153
154
155
# File 'lib/reality/entity.rb', line 153

def to_s
  name
end