inat-get 0.8.0.11
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 +7 -0
- data/LICENSE +674 -0
- data/README.md +16 -0
- data/Rakefile +4 -0
- data/bin/inat-get +59 -0
- data/docs/logo.png +0 -0
- data/inat-get.gemspec +33 -0
- data/lib/extra/enum.rb +184 -0
- data/lib/extra/period.rb +252 -0
- data/lib/extra/uuid.rb +90 -0
- data/lib/inat/app/application.rb +50 -0
- data/lib/inat/app/config/messagelevel.rb +22 -0
- data/lib/inat/app/config/shiftage.rb +24 -0
- data/lib/inat/app/config/updatemode.rb +20 -0
- data/lib/inat/app/config.rb +296 -0
- data/lib/inat/app/globals.rb +80 -0
- data/lib/inat/app/info.rb +21 -0
- data/lib/inat/app/logging.rb +35 -0
- data/lib/inat/app/preamble.rb +27 -0
- data/lib/inat/app/status.rb +74 -0
- data/lib/inat/app/task/context.rb +47 -0
- data/lib/inat/app/task/dsl.rb +24 -0
- data/lib/inat/app/task.rb +75 -0
- data/lib/inat/data/api.rb +218 -0
- data/lib/inat/data/cache.rb +9 -0
- data/lib/inat/data/db.rb +87 -0
- data/lib/inat/data/ddl.rb +18 -0
- data/lib/inat/data/entity/comment.rb +29 -0
- data/lib/inat/data/entity/flag.rb +22 -0
- data/lib/inat/data/entity/identification.rb +45 -0
- data/lib/inat/data/entity/observation.rb +172 -0
- data/lib/inat/data/entity/observationphoto.rb +25 -0
- data/lib/inat/data/entity/observationsound.rb +26 -0
- data/lib/inat/data/entity/photo.rb +31 -0
- data/lib/inat/data/entity/place.rb +57 -0
- data/lib/inat/data/entity/project.rb +94 -0
- data/lib/inat/data/entity/projectadmin.rb +21 -0
- data/lib/inat/data/entity/projectobservationrule.rb +50 -0
- data/lib/inat/data/entity/request.rb +58 -0
- data/lib/inat/data/entity/sound.rb +27 -0
- data/lib/inat/data/entity/taxon.rb +94 -0
- data/lib/inat/data/entity/user.rb +67 -0
- data/lib/inat/data/entity/vote.rb +22 -0
- data/lib/inat/data/entity.rb +291 -0
- data/lib/inat/data/enums/conservationstatus.rb +30 -0
- data/lib/inat/data/enums/geoprivacy.rb +14 -0
- data/lib/inat/data/enums/iconictaxa.rb +23 -0
- data/lib/inat/data/enums/identificationcategory.rb +13 -0
- data/lib/inat/data/enums/licensecode.rb +16 -0
- data/lib/inat/data/enums/projectadminrole.rb +11 -0
- data/lib/inat/data/enums/projecttype.rb +37 -0
- data/lib/inat/data/enums/qualitygrade.rb +12 -0
- data/lib/inat/data/enums/rank.rb +60 -0
- data/lib/inat/data/model.rb +551 -0
- data/lib/inat/data/query.rb +1145 -0
- data/lib/inat/data/sets/dataset.rb +104 -0
- data/lib/inat/data/sets/list.rb +190 -0
- data/lib/inat/data/sets/listers.rb +15 -0
- data/lib/inat/data/sets/wrappers.rb +137 -0
- data/lib/inat/data/types/extras.rb +88 -0
- data/lib/inat/data/types/location.rb +89 -0
- data/lib/inat/data/types/std.rb +293 -0
- data/lib/inat/report/table.rb +135 -0
- data/lib/inat/utils/deep.rb +30 -0
- metadata +137 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'extra/uuid'
|
4
|
+
|
5
|
+
require_relative '../types/std'
|
6
|
+
require_relative '../types/extras'
|
7
|
+
require_relative '../entity'
|
8
|
+
|
9
|
+
# require_relative 'observation'
|
10
|
+
# require_relative 'photo'
|
11
|
+
|
12
|
+
autoload :Observation, 'inat/data/entity/observation'
|
13
|
+
autoload :Photo, 'inat/data/entity/photo'
|
14
|
+
|
15
|
+
class ObservationPhoto < Entity
|
16
|
+
|
17
|
+
table :observation_photos
|
18
|
+
|
19
|
+
field :observation, type: Observation, index: true
|
20
|
+
|
21
|
+
field :uuid, type: UUID, unique: true
|
22
|
+
field :position, type: Integer, index: true
|
23
|
+
field :photo, type: Photo, required: true
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'extra/uuid'
|
4
|
+
|
5
|
+
require_relative '../types/std'
|
6
|
+
require_relative '../types/extras'
|
7
|
+
require_relative '../entity'
|
8
|
+
|
9
|
+
# require_relative 'observation'
|
10
|
+
# require_relative 'sound'
|
11
|
+
|
12
|
+
# class Observation < Entity; end
|
13
|
+
|
14
|
+
autoload :Observation, 'inat/data/entity/observation'
|
15
|
+
autoload :Sound, 'inat/data/entity/sound'
|
16
|
+
|
17
|
+
class ObservationSound < Entity
|
18
|
+
|
19
|
+
table :observation_sounds
|
20
|
+
|
21
|
+
field :observation, type: Observation, index: true
|
22
|
+
|
23
|
+
field :uuid, type: UUID, unique: true
|
24
|
+
field :sound, type: Sound, required: true
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../types/std'
|
4
|
+
require_relative '../types/extras'
|
5
|
+
require_relative '../entity'
|
6
|
+
|
7
|
+
autoload :Observation, 'inat/data/entity/observation'
|
8
|
+
|
9
|
+
class Photo < Entity
|
10
|
+
|
11
|
+
table :photos
|
12
|
+
|
13
|
+
field :license_code, type: Symbol, index: true
|
14
|
+
field :url, type: URI, required: true
|
15
|
+
field :square_url, type: URI
|
16
|
+
field :medium_url, type: URI
|
17
|
+
field :small_url, type: URI
|
18
|
+
field :large_url, type: URI
|
19
|
+
field :original_url, type: URI
|
20
|
+
field :attribution, type: String
|
21
|
+
field :hidden, type: Boolean, index: true
|
22
|
+
|
23
|
+
links :flags, item_type: Flag
|
24
|
+
|
25
|
+
ignore :original_dimensions # TODO: сделать нормальный тип
|
26
|
+
|
27
|
+
ignore :moderator_actions # TODO: разобраться
|
28
|
+
field :native_page_url, type: URI
|
29
|
+
ignore :native_photo_id
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../types/std'
|
4
|
+
require_relative '../types/extras'
|
5
|
+
require_relative '../types/location'
|
6
|
+
require_relative '../entity'
|
7
|
+
|
8
|
+
autoload :Observation, 'inat/data/entity/observation'
|
9
|
+
|
10
|
+
class Place < Entity
|
11
|
+
|
12
|
+
extend BySLUG
|
13
|
+
|
14
|
+
api_path :places
|
15
|
+
api_part :path
|
16
|
+
api_limit 500
|
17
|
+
|
18
|
+
table :places
|
19
|
+
|
20
|
+
field :uuid, type: UUID, unique: true
|
21
|
+
field :name, type: String, index: true, required: true
|
22
|
+
field :slug, type: Symbol, index: true
|
23
|
+
field :display_name, type: String, index: true
|
24
|
+
field :bbox_area, type: Float
|
25
|
+
field :admin_level, type: Integer, index: true
|
26
|
+
field :place_type, type: Integer, index: true
|
27
|
+
field :location, type: Location
|
28
|
+
|
29
|
+
ignore :geometry_geojson # TODO: implement
|
30
|
+
ignore :bounding_box_geojson
|
31
|
+
|
32
|
+
links :ancestor_places, item_type: Place, table_name: :place_ancestors, link_field: :ancestor_id, index: true
|
33
|
+
|
34
|
+
def === other
|
35
|
+
self.id == other.id && other.ancestor_place_ids.include?(self.id)
|
36
|
+
end
|
37
|
+
|
38
|
+
def sort_key
|
39
|
+
display_name
|
40
|
+
end
|
41
|
+
|
42
|
+
class << self
|
43
|
+
|
44
|
+
def DDL
|
45
|
+
super +
|
46
|
+
"INSERT OR REPLACE INTO places (id, uuid, name, display_name) VALUES (59614, '00000000-0000-0000-0000-000000000000', 'World', 'Весь мир');\n"
|
47
|
+
# Если верить API, то идентификатор такой есть, а записи для него нет.
|
48
|
+
# Вставляем ему искусственно некоторые данные для того, чтобы не запрашивать впустую каждый раз, как он встречается.
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_s
|
54
|
+
"<a href=\"https://www.inaturalist.org/places/#{ id }\"><i class=\"fa fa-globe\"></i> #{ display_name || name }</a>"
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../types/std'
|
4
|
+
require_relative '../types/extras'
|
5
|
+
require_relative '../types/location'
|
6
|
+
require_relative '../entity'
|
7
|
+
require_relative '../enums/projecttype'
|
8
|
+
|
9
|
+
# require_relative 'projectadmin'
|
10
|
+
# require_relative 'projectobservationrule'
|
11
|
+
|
12
|
+
autoload :Observation, 'inat/data/entity/observation'
|
13
|
+
autoload :User, 'inat/data/entity/user'
|
14
|
+
autoload :Place, 'inat/data/entity/place'
|
15
|
+
autoload :ProjectAdmin, 'inat/data/entity/projectadmin'
|
16
|
+
autoload :ProjectObservationRule, 'inat/data/entity/projectobservationrule'
|
17
|
+
autoload :Flag, 'inat/data/entity/flag'
|
18
|
+
autoload :Taxon, 'inat/data/entity/taxon'
|
19
|
+
|
20
|
+
class Project < Entity
|
21
|
+
|
22
|
+
extend BySLUG
|
23
|
+
|
24
|
+
api_path :projects
|
25
|
+
api_part :query
|
26
|
+
api_limit 200
|
27
|
+
|
28
|
+
table :projects
|
29
|
+
|
30
|
+
field :slug, type: Symbol, index: true
|
31
|
+
field :title, type: String, index: true, required: true
|
32
|
+
field :description, type: String
|
33
|
+
field :project_type, type: ProjectType, index: true
|
34
|
+
field :is_umbrella, type: Boolean, index: true
|
35
|
+
field :created_at, type: Time
|
36
|
+
field :updated_at, type: Time
|
37
|
+
field :observation_requirements_updated_at, type: Time
|
38
|
+
field :prefers_user_trust, type: Boolean
|
39
|
+
field :icon, type: URI
|
40
|
+
field :icon_file_name, type: String
|
41
|
+
field :header_image_url, type: URI
|
42
|
+
field :header_image_file_name, type: String
|
43
|
+
field :header_image_contain, type: Boolean
|
44
|
+
field :banner_color, type: String # TODO: сделать тип
|
45
|
+
field :hide_title, type: Boolean
|
46
|
+
field :user, type: User, index: true
|
47
|
+
field :location, type: Location
|
48
|
+
|
49
|
+
field :place, type: Place, index: true
|
50
|
+
|
51
|
+
# links :users, item_type: User
|
52
|
+
# TODO: разобраться как грузить пачками
|
53
|
+
ignore :users
|
54
|
+
ignore :user_ids
|
55
|
+
|
56
|
+
backs :admins, item_type: ProjectAdmin, owned: true
|
57
|
+
backs :project_observation_rules, item_type: ProjectObservationRule, owned: true
|
58
|
+
|
59
|
+
links :flags, item_type: Flag, index: true
|
60
|
+
|
61
|
+
links :subprojects, item_type: Project, table_name: :project_children, link_field: :child_id, owned: false
|
62
|
+
|
63
|
+
links :included_taxa, item_type: Taxon, ids_field: :included_taxon_ids, table_name: :project_rule_taxa, owned: false
|
64
|
+
links :excluded_taxa, item_type: Taxon, ids_field: :excluded_taxon_ids, table_name: :project_rule_excluded_taxa, owned: false
|
65
|
+
links :included_places, item_type: Place, ids_field: :included_place_ids, table_name: :project_rule_places, owned: false
|
66
|
+
links :excluded_places, item_type: Place, ids_field: :excluded_places_ids, table_name: :project_rule_excluded_places, owned: false
|
67
|
+
|
68
|
+
links :observations, item_type: Observation, table_name: :project_observations, owned: false
|
69
|
+
|
70
|
+
ignore :latitude
|
71
|
+
ignore :longitude
|
72
|
+
|
73
|
+
# block :latitude, type: Float do |value|
|
74
|
+
# @location ||= Location::new nil, nil
|
75
|
+
# @location.latitude = value
|
76
|
+
# end
|
77
|
+
|
78
|
+
# block :longitude, type: Float do |value|
|
79
|
+
# @location ||= Location::new nil, nil
|
80
|
+
# @location.longitude = value
|
81
|
+
# end
|
82
|
+
|
83
|
+
# # TODO: разобраться и сделать связи с местами и таксонами
|
84
|
+
ignore :project_observation_fields
|
85
|
+
ignore :site_features
|
86
|
+
ignore :terms
|
87
|
+
ignore :search_parameters
|
88
|
+
ignore :rule_preferences
|
89
|
+
|
90
|
+
def to_s
|
91
|
+
"<a href=\"https://www.inaturalist.org/projects/#{ id }\"><i class=\"fa fa-briefcase\"></i> #{ title }</a>"
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../types/std'
|
4
|
+
require_relative '../types/extras'
|
5
|
+
require_relative '../entity'
|
6
|
+
require_relative '../enums/projectadminrole'
|
7
|
+
|
8
|
+
# require_relative 'project'
|
9
|
+
# autoload :Project, 'inat/data/entity/project'
|
10
|
+
|
11
|
+
class Project < Entity; end
|
12
|
+
|
13
|
+
class ProjectAdmin < Entity
|
14
|
+
|
15
|
+
table :project_admins
|
16
|
+
|
17
|
+
field :project, type: Project, index: true
|
18
|
+
field :role, type: ProjectAdminRole, index: true, required: true
|
19
|
+
field :user, type: User, index: true, required: true
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../types/std'
|
4
|
+
require_relative '../types/extras'
|
5
|
+
require_relative '../entity'
|
6
|
+
|
7
|
+
# require_relative 'project'
|
8
|
+
# autoload :Project, 'inat/data/entity/project'
|
9
|
+
|
10
|
+
class Project < Entity; end
|
11
|
+
|
12
|
+
class ProjectObservationRule < Entity
|
13
|
+
|
14
|
+
table :project_observation_rules
|
15
|
+
|
16
|
+
field :project, type: Project, index: true
|
17
|
+
|
18
|
+
field :operator, type: Symbol, index: true, required: true
|
19
|
+
field :operand_type, type: Symbol, index: true
|
20
|
+
field :operand_id, type: Integer, index: true
|
21
|
+
|
22
|
+
class << self
|
23
|
+
|
24
|
+
def DDL
|
25
|
+
super +
|
26
|
+
"CREATE VIEW IF NOT EXISTS project_children AS\n" +
|
27
|
+
" SELECT project_id, operand_id as child_id\n" +
|
28
|
+
" FROM project_observation_rules\n" +
|
29
|
+
" WHERE operator = 'in_project?' AND operand_type = 'Project';\n" +
|
30
|
+
"CREATE VIEW IF NOT EXISTS project_rule_taxa AS\n" +
|
31
|
+
" SELECT project_id, operand_id as taxon_id\n" +
|
32
|
+
" FROM project_observation_rules\n" +
|
33
|
+
" WHERE operator = 'in_taxon?' AND operand_type = 'Taxon';\n" +
|
34
|
+
"CREATE VIEW IF NOT EXISTS project_rule_places AS\n" +
|
35
|
+
" SELECT project_id, operand_id as place_id\n" +
|
36
|
+
" FROM project_observation_rules\n" +
|
37
|
+
" WHERE operator = 'observed_in_place?' AND operand_type = 'Place';\n" +
|
38
|
+
"CREATE VIEW IF NOT EXISTS project_rule_excluded_taxa AS\n" +
|
39
|
+
" SELECT project_id, operand_id as taxon_id\n" +
|
40
|
+
" FROM project_observation_rules\n" +
|
41
|
+
" WHERE operator = 'not_in_taxon?' AND operand_type = 'Taxon';\n" +
|
42
|
+
"CREATE VIEW IF NOT EXISTS project_rule_excluded_places AS\n" +
|
43
|
+
" SELECT project_id, operand_id as place_id\n" +
|
44
|
+
" FROM project_observation_rules\n" +
|
45
|
+
" WHERE operator = 'not_observed_in_place?' AND operand_type = 'Place';\n"
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../types/std'
|
4
|
+
require_relative '../types/extras'
|
5
|
+
require_relative '../entity'
|
6
|
+
require_relative '../db'
|
7
|
+
|
8
|
+
autoload :Observation, 'inat/data/entity/observation'
|
9
|
+
autoload :Project, 'inat/data/entity/project'
|
10
|
+
|
11
|
+
class Request < Entity
|
12
|
+
|
13
|
+
table :requests
|
14
|
+
|
15
|
+
field :time, type: Time, index: true
|
16
|
+
field :query, type: String, unique: true
|
17
|
+
|
18
|
+
field :project, type: Project, index: true
|
19
|
+
|
20
|
+
links :observations, item_type: Observation, index: true
|
21
|
+
|
22
|
+
class << self
|
23
|
+
|
24
|
+
def DDL
|
25
|
+
super +
|
26
|
+
"CREATE VIEW IF NOT EXISTS project_observations AS\n" +
|
27
|
+
" SELECT r.project_id, ro.observation_id\n" +
|
28
|
+
" FROM requests r, request_observations ro\n" +
|
29
|
+
" WHERE r.id = ro.request_id AND r.project_id IS NOT NULL;\n"
|
30
|
+
end
|
31
|
+
|
32
|
+
def create query_string, project_id
|
33
|
+
update do
|
34
|
+
max_id = DB.execute("SELECT max(id) AS id FROM requests;").map{ |r| r['id'] }.first
|
35
|
+
new_id = if max_id == nil
|
36
|
+
1
|
37
|
+
else
|
38
|
+
max_id + 1
|
39
|
+
end
|
40
|
+
@entities ||= {}
|
41
|
+
@entities[new_id] ||= new new_id
|
42
|
+
@entities[new_id].time = Time::at(0)
|
43
|
+
@entities[new_id].query = query_string
|
44
|
+
@entities[new_id].project_id = project_id
|
45
|
+
@entities[new_id].save
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
attr_accessor :active
|
52
|
+
|
53
|
+
def initialize id
|
54
|
+
super(id)
|
55
|
+
@active = false
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../types/std'
|
4
|
+
require_relative '../types/extras'
|
5
|
+
require_relative '../entity'
|
6
|
+
|
7
|
+
autoload :Observation, 'inat/data/entity/observation'
|
8
|
+
|
9
|
+
class Sound < Entity
|
10
|
+
|
11
|
+
table :sounds
|
12
|
+
|
13
|
+
field :license_code, type: LicenseCode, index: true
|
14
|
+
field :attribution, type: String
|
15
|
+
field :file_url, type: URI
|
16
|
+
field :file_content_type, type: Symbol, index: true
|
17
|
+
field :play_local, type: Boolean
|
18
|
+
field :subtype, type: Symbol, index: true
|
19
|
+
field :hidden, type: Boolean, index: true
|
20
|
+
|
21
|
+
links :flags, item_type: Flag
|
22
|
+
|
23
|
+
ignore :native_sound_id # TODO: разобраться
|
24
|
+
ignore :secret_token
|
25
|
+
ignore :moderator_actions
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../types/std'
|
4
|
+
require_relative '../types/extras'
|
5
|
+
require_relative '../entity'
|
6
|
+
|
7
|
+
require_relative '../enums/rank'
|
8
|
+
require_relative '../enums/iconictaxa'
|
9
|
+
|
10
|
+
require_relative 'photo'
|
11
|
+
|
12
|
+
autoload :Observation, 'inat/data/entity/observation'
|
13
|
+
# autoload :Photo, 'inat/data/entity/photo'
|
14
|
+
|
15
|
+
class Taxon < Entity
|
16
|
+
|
17
|
+
api_path :taxa
|
18
|
+
api_part :query
|
19
|
+
api_limit 200
|
20
|
+
|
21
|
+
table :taxa
|
22
|
+
|
23
|
+
field :is_active, type: Boolean, index: true
|
24
|
+
# field :ancestry, type: Ancestry
|
25
|
+
# field :min_species_ancestry, type: Ancestry
|
26
|
+
field :endemic, type: Boolean
|
27
|
+
field :iconic_taxon, type: Taxon
|
28
|
+
field :min_species_taxon, type: Taxon
|
29
|
+
field :threatened, type: Boolean, index: true
|
30
|
+
field :rank_level, type: Float, index: true
|
31
|
+
field :introduced, type: Boolean
|
32
|
+
field :native, type: Boolean
|
33
|
+
field :parent, type: Taxon
|
34
|
+
field :name, type: String, index: true, required: true
|
35
|
+
field :rank, type: Rank, index: true
|
36
|
+
field :extinct, type: Boolean
|
37
|
+
field :created_at, type: Time
|
38
|
+
field :default_photo, type: Photo
|
39
|
+
field :taxon_changes_count, type: Integer
|
40
|
+
field :taxon_schemes_count, type: Integer
|
41
|
+
# field :observations_count, type: Integer
|
42
|
+
field :photos_locked, type: Boolean
|
43
|
+
# field :universal_search_rank, type: Integer
|
44
|
+
field :wikipedia_url, type: URI
|
45
|
+
field :wikipedia_summary, type: String
|
46
|
+
field :iconic_taxon_name, type: IconicTaxa, index: true
|
47
|
+
# field :iconic_taxon, type: Taxon, index: true
|
48
|
+
field :preferred_common_name, type: String
|
49
|
+
field :english_common_name, type: String
|
50
|
+
field :vision, type: Boolean
|
51
|
+
|
52
|
+
links :ancestors, item_type: Taxon, link_field: :ancestor_id
|
53
|
+
links :taxon_photos, item_type: Photo, table_name: :taxon_photos
|
54
|
+
|
55
|
+
backs :children, item_type: Taxon, ids_field: :child_ids, back_field: :parent_id, owned: false
|
56
|
+
|
57
|
+
ignore :flag_counts # TODO: разобраться
|
58
|
+
ignore :current_synonymous_taxon_ids
|
59
|
+
ignore :atlas_id
|
60
|
+
ignore :complete_species_count
|
61
|
+
ignore :conservation_statuses
|
62
|
+
ignore :conservation_status
|
63
|
+
ignore :listed_taxa
|
64
|
+
ignore :complete_rank
|
65
|
+
|
66
|
+
ignore :ancestry # TODO: подумать и сделать обязательно
|
67
|
+
ignore :min_species_ancestry
|
68
|
+
ignore :establishment_means
|
69
|
+
ignore :preferred_establishment_means
|
70
|
+
|
71
|
+
ignore :observations_count
|
72
|
+
ignore :universal_search_rank
|
73
|
+
|
74
|
+
def === other
|
75
|
+
other.id == self.id || other.ancestor_ids.include?(self.id)
|
76
|
+
end
|
77
|
+
|
78
|
+
def sort_key
|
79
|
+
[ iconic_taxon_name || IconicTaxa::UNKNOWN, name ]
|
80
|
+
end
|
81
|
+
|
82
|
+
private def prepare_name name
|
83
|
+
name.downcase.gsub(' ', ' ').capitalize
|
84
|
+
end
|
85
|
+
|
86
|
+
def to_s
|
87
|
+
if preferred_common_name
|
88
|
+
"<a href=\"https://www.inaturalist.org/taxa/#{ id }\"><i class=\"icon-iconic-#{ (iconic_taxon_name || IconicTaxa::UNKNOWN).to_s.downcase }\" style=\"font-size:1.5em;height:1em;line-height:1em;\"></i> #{ prepare_name(preferred_common_name) } <i>(#{ prepare_name(name) })</i></a>"
|
89
|
+
else
|
90
|
+
"<a href=\"https://www.inaturalist.org/taxa/#{ id }\"><i class=\"icon-iconic-#{ (iconic_taxon_name || IconicTaxa::UNKNOWN).to_s.downcase }\" style=\"font-size:1.5em;height:1em;line-height:1em;\"></i> <i>#{ prepare_name(name) }</i></a>"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../types/std'
|
4
|
+
require_relative '../types/extras'
|
5
|
+
require_relative '../entity'
|
6
|
+
|
7
|
+
autoload :Observation, 'inat/data/entity/observation'
|
8
|
+
|
9
|
+
class User < Entity
|
10
|
+
|
11
|
+
api_path :users
|
12
|
+
api_part :path
|
13
|
+
api_limit 1
|
14
|
+
|
15
|
+
table :users
|
16
|
+
|
17
|
+
field :login, type: String, index: true, required: true
|
18
|
+
field :spam, type: Boolean
|
19
|
+
field :suspended, type: Boolean, index: true
|
20
|
+
field :created_at, type: Time, index: true
|
21
|
+
field :site_id, type: Integer, index: true
|
22
|
+
field :login_autocomplete, type: String
|
23
|
+
field :login_exact, type: String
|
24
|
+
field :name, type: String, index: true
|
25
|
+
field :name_autocomplete, type: String
|
26
|
+
field :orcid, type: URI
|
27
|
+
field :icon, type: URI
|
28
|
+
field :icon_url, type: URI
|
29
|
+
field :observations_count, type: Integer
|
30
|
+
field :identifications_count, type: Integer
|
31
|
+
field :journal_posts_count, type: Integer
|
32
|
+
field :activity_count, type: Integer
|
33
|
+
field :species_count, type: Integer
|
34
|
+
field :universal_search_rank, type: Integer
|
35
|
+
|
36
|
+
ignore :roles # TODO: разобраться
|
37
|
+
ignore :preferences
|
38
|
+
|
39
|
+
def sort_key
|
40
|
+
login
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.by_login login
|
44
|
+
@entities ||= {}
|
45
|
+
results = @entities.values.select { |e| e.login == login.to_s }
|
46
|
+
if results.empty?
|
47
|
+
data = DB.execute "SELECT * FROM users WHERE login = ?", login.to_s
|
48
|
+
results = from_db_rows data
|
49
|
+
end
|
50
|
+
if results.empty?
|
51
|
+
data = API.query 'users/autocomplete', first_only: true, q: login
|
52
|
+
results = data.select { |u| u['login'] == login.to_s }.map { |d| parse(d) }
|
53
|
+
end
|
54
|
+
if results.empty?
|
55
|
+
nil
|
56
|
+
else
|
57
|
+
results.first
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_s
|
62
|
+
title = ''
|
63
|
+
title = " title=\"#{ name }\"" if name
|
64
|
+
"<a#{ title } href=\"https://www.inaturalist.org/people/#{ id }\"><i class=\"glyphicon glyphicon-user\"></i></a> @#{ login }"
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../types/std'
|
4
|
+
require_relative '../types/extras'
|
5
|
+
require_relative '../entity'
|
6
|
+
|
7
|
+
autoload :Observation, 'inat/data/entity/observation'
|
8
|
+
autoload :User, 'inat/data/entity/user'
|
9
|
+
|
10
|
+
class Vote < Entity
|
11
|
+
|
12
|
+
table :votes
|
13
|
+
|
14
|
+
# field :observation, type: Observation, index: true, required: true
|
15
|
+
|
16
|
+
field :created_at, type: Time, index: true, required: true
|
17
|
+
field :vote_flag, type: Boolean, index: true
|
18
|
+
field :user, type: User, index: true
|
19
|
+
|
20
|
+
ignore :vote_scope # TODO: разобраться
|
21
|
+
|
22
|
+
end
|