rgovdata 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rvmrc +2 -0
- data/CHANGELOG +7 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +48 -0
- data/LICENSE +20 -0
- data/README.rdoc +114 -0
- data/Rakefile +61 -0
- data/bin/rgd +12 -0
- data/examples/all_quakes.rb +8 -0
- data/examples/arbitrary_data.rb +26 -0
- data/examples/catalog_traversal.rb +34 -0
- data/examples/earthquakes.rb +5 -0
- data/lib/rgovdata.rb +4 -0
- data/lib/rgovdata/catalog.rb +4 -0
- data/lib/rgovdata/catalog/catalog.rb +79 -0
- data/lib/rgovdata/catalog/dn.rb +63 -0
- data/lib/rgovdata/catalog/registry_strategy/internal_registry.rb +12 -0
- data/lib/rgovdata/catalog/registry_strategy/registry_strategy.rb +26 -0
- data/lib/rgovdata/config.rb +5 -0
- data/lib/rgovdata/config/common_config.rb +13 -0
- data/lib/rgovdata/config/config.rb +133 -0
- data/lib/rgovdata/data/config_template.yml +19 -0
- data/lib/rgovdata/data/sg/registry.yml +147 -0
- data/lib/rgovdata/data/template.rb +27 -0
- data/lib/rgovdata/data/us/registry.yml +12 -0
- data/lib/rgovdata/service.rb +10 -0
- data/lib/rgovdata/service/csv_service.rb +3 -0
- data/lib/rgovdata/service/dataset/csv_dataset.rb +43 -0
- data/lib/rgovdata/service/dataset/dataset.rb +91 -0
- data/lib/rgovdata/service/dataset/file_dataset.rb +46 -0
- data/lib/rgovdata/service/dataset/odata_dataset.rb +31 -0
- data/lib/rgovdata/service/file_service.rb +10 -0
- data/lib/rgovdata/service/listing.rb +47 -0
- data/lib/rgovdata/service/odata_service.rb +50 -0
- data/lib/rgovdata/service/service.rb +93 -0
- data/lib/rgovdata/shell/shell.rb +157 -0
- data/lib/rgovdata/version.rb +9 -0
- data/rgovdata.gemspec +128 -0
- data/spec/fixtures/sample.csv +821 -0
- data/spec/integration/service/sg/nlb_spec.rb +57 -0
- data/spec/integration/service/sg/places_spec.rb +73 -0
- data/spec/integration/service/us/eqs7day-M1_spec.rb +57 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/config_examples.rb +8 -0
- data/spec/support/mocks.rb +22 -0
- data/spec/support/utility.rb +18 -0
- data/spec/unit/catalog/base_spec.rb +93 -0
- data/spec/unit/catalog/registry_strategy_spec.rb +28 -0
- data/spec/unit/config/config_spec.rb +130 -0
- data/spec/unit/data/template_spec.rb +32 -0
- data/spec/unit/service/dataset/csv_dataset_spec.rb +42 -0
- data/spec/unit/service/dataset/dataset_spec.rb +37 -0
- data/spec/unit/service/dataset/file_dataset_spec.rb +40 -0
- data/spec/unit/service/dataset/odata_dataset_spec.rb +36 -0
- data/spec/unit/service/file_service_spec.rb +25 -0
- data/spec/unit/service/listing_spec.rb +100 -0
- data/spec/unit/service/odata_service_spec.rb +42 -0
- data/spec/unit/service/service_spec.rb +82 -0
- data/spec/unit/shell/shell_spec.rb +10 -0
- metadata +228 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
# This module defines the basic naming interface for catalog objects
|
2
|
+
# Override these methods as required
|
3
|
+
module RGovData::Dn
|
4
|
+
|
5
|
+
# Returns the human-readable unique id
|
6
|
+
def id
|
7
|
+
nameparts = []
|
8
|
+
if defined? realm
|
9
|
+
nameparts.push('/')
|
10
|
+
nameparts.push(realm)
|
11
|
+
end
|
12
|
+
nameparts.push(service_key) if defined?(service_key) && service_key.present?
|
13
|
+
nameparts.push(dataset_key) if defined?(dataset_key) && dataset_key.present?
|
14
|
+
nameparts.join('/')
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns a rails-compatible ID
|
18
|
+
def to_param
|
19
|
+
id.gsub('/',':')
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the human version of the object name/identification
|
23
|
+
def to_s
|
24
|
+
"#{id} [#{self.class.name}]"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns array of attributes that describe the specific entity
|
28
|
+
# By default, guesses based on instance variables
|
29
|
+
def meta_attributes
|
30
|
+
a = [:id]
|
31
|
+
instance_variables.each do |v|
|
32
|
+
n = v.to_s.gsub('@','').to_sym
|
33
|
+
a << n if self.respond_to?(n)
|
34
|
+
end
|
35
|
+
a
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns a hash that fully describes this service and can be used as a parameter to +new+
|
39
|
+
# By default, returns a hash based on meta_attributes
|
40
|
+
def initialization_hash
|
41
|
+
h = {}
|
42
|
+
meta_attributes.each do |attribute|
|
43
|
+
h.merge!(attribute => self.send(attribute))
|
44
|
+
end
|
45
|
+
h
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns array of attributes that describe the records of the specific entity
|
49
|
+
# By default, it is nil (meaning indeterminate)
|
50
|
+
def attributes
|
51
|
+
@attributes
|
52
|
+
end
|
53
|
+
|
54
|
+
# Generic interface to return the currently applicable record set
|
55
|
+
def records
|
56
|
+
if defined? datasets
|
57
|
+
datasets
|
58
|
+
else
|
59
|
+
[]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class RGovData::InternalRegistry < RGovData::RegistryStrategy
|
2
|
+
|
3
|
+
# Returns the list of services for the realm
|
4
|
+
# based on internal yml file
|
5
|
+
def load_services
|
6
|
+
service_array = []
|
7
|
+
registry = RGovData::Template.get('registry.yml',realm)
|
8
|
+
YAML::load_documents( registry ) { |doc| service_array << doc }
|
9
|
+
service_array
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class RGovData::RegistryStrategy
|
2
|
+
attr_accessor :realm
|
3
|
+
|
4
|
+
class << self
|
5
|
+
# Returns the appropriate RegistryStrategy for the given realm
|
6
|
+
# +realm+ is the required realm
|
7
|
+
def instance_for_realm(realm)
|
8
|
+
# TODO: this is where we can abstract different registry schemes
|
9
|
+
# e.g by default we will look for a class called Rgovdata::<realm>Registry (Rgovdata::ZhRegistry)
|
10
|
+
# else we take the default strategy
|
11
|
+
# Currently this just defaults to internal registry:
|
12
|
+
RGovData::InternalRegistry.new(realm)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# +new+ accepts realm parameter
|
17
|
+
def initialize(default_realm=nil)
|
18
|
+
@realm = default_realm
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the list of services for the realm
|
22
|
+
def load_services
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# This module is used to include basic support to access
|
2
|
+
# the shared RGovData::Config instance
|
3
|
+
module RGovData::CommonConfig
|
4
|
+
# Returns the current config instance
|
5
|
+
def config
|
6
|
+
RGovData::Config.instance
|
7
|
+
end
|
8
|
+
# Sets the requirement to have a config file
|
9
|
+
# Must be called before config is invoked
|
10
|
+
def require_config_file
|
11
|
+
RGovData::Config.require_config_file
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'singleton'
|
3
|
+
|
4
|
+
class RGovData::Config
|
5
|
+
include Singleton
|
6
|
+
BASE_NAME = 'rgovdata.conf'
|
7
|
+
|
8
|
+
class ConfigError < StandardError
|
9
|
+
end
|
10
|
+
class ConfigurationFileNotFound < ConfigError
|
11
|
+
end
|
12
|
+
class ConfigurationFileInitialized < ConfigError
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_accessor :default_realm, :credentialsets
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
load_default_config
|
19
|
+
end
|
20
|
+
|
21
|
+
# Reloads configuraiton from default config provider
|
22
|
+
# - rails config file (if used in Rails)
|
23
|
+
# - current directory
|
24
|
+
# - environment settings
|
25
|
+
def load_default_config
|
26
|
+
clear
|
27
|
+
# load default config
|
28
|
+
if rails_root
|
29
|
+
# if rails env, load from Rails.root.join('config',BASE_NAME)
|
30
|
+
load_config(rails_root.join('config',BASE_NAME),self.class.default_loader_options)
|
31
|
+
elsif
|
32
|
+
# else load from pwd
|
33
|
+
load_config(self.class.default_config_file,self.class.default_loader_options)
|
34
|
+
else
|
35
|
+
# else just refresh_from_env
|
36
|
+
refresh_from_env
|
37
|
+
end
|
38
|
+
end
|
39
|
+
# Returns the rails root, if the Rails environment is available
|
40
|
+
def rails_root
|
41
|
+
Rails.root if defined?(Rails)
|
42
|
+
end
|
43
|
+
protected :rails_root
|
44
|
+
|
45
|
+
def load_config(configfilepath, options = {})
|
46
|
+
options.reverse_merge!(:generate_default => true,:required => true)
|
47
|
+
unless File.exists?(configfilepath)
|
48
|
+
self.class.reset_configfile(configfilepath) if options[:generate_default]
|
49
|
+
if File.exists?(configfilepath)
|
50
|
+
raise ConfigurationFileInitialized.new("\n
|
51
|
+
No configuration file found.
|
52
|
+
A new file has been initialized at: #{configfilepath}
|
53
|
+
Please review the configuration and retry..\n\n\n")
|
54
|
+
elsif options[:required]
|
55
|
+
raise ConfigurationFileNotFound.new("cannot load config file #{configfilepath}")
|
56
|
+
else
|
57
|
+
return
|
58
|
+
end
|
59
|
+
end
|
60
|
+
update_settings(OpenStruct.new(YAML::load(File.read(configfilepath))))
|
61
|
+
end
|
62
|
+
|
63
|
+
# Updates attributes from config, including env override
|
64
|
+
# +config+ OpenStruct structure
|
65
|
+
def update_settings(config)
|
66
|
+
@credentialsets.merge!(config.credentialsets||{})
|
67
|
+
@default_realm = config.default_realm.to_sym if config.default_realm
|
68
|
+
refresh_from_env
|
69
|
+
end
|
70
|
+
protected :update_settings
|
71
|
+
|
72
|
+
# Clears the current configuration
|
73
|
+
def clear
|
74
|
+
@credentialsets = {}
|
75
|
+
@default_realm = nil
|
76
|
+
end
|
77
|
+
|
78
|
+
# Prints current status
|
79
|
+
def show_status
|
80
|
+
if credentialsets
|
81
|
+
puts "credential sets available: #{credentialsets.keys.join(',')}"
|
82
|
+
puts credentialsets.inspect
|
83
|
+
else
|
84
|
+
puts "credential sets available: none"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Sets environment overrides for supported settings
|
89
|
+
def refresh_from_env
|
90
|
+
if ENV['projectnimbus_account_key'] || ENV['projectnimbus_unique_user_id']
|
91
|
+
@credentialsets['projectnimbus'] ||= {}
|
92
|
+
@credentialsets['projectnimbus'].merge!({'AccountKey'=> ENV['projectnimbus_account_key']}) if ENV['projectnimbus_account_key']
|
93
|
+
@credentialsets['projectnimbus'].merge!({'UniqueUserID'=> ENV['projectnimbus_unique_user_id']}) if ENV['projectnimbus_unique_user_id']
|
94
|
+
end
|
95
|
+
if ENV['rgovdata_username'] || ENV['rgovdata_password']
|
96
|
+
@credentialsets['basic'] ||= {}
|
97
|
+
@credentialsets['basic'].merge!({'username'=> ENV['rgovdata_username']}) if ENV['rgovdata_username']
|
98
|
+
@credentialsets['basic'].merge!({'password'=> ENV['rgovdata_password']}) if ENV['rgovdata_password']
|
99
|
+
end
|
100
|
+
end
|
101
|
+
protected :refresh_from_env
|
102
|
+
|
103
|
+
class << self
|
104
|
+
def reset_configfile(configfilepath)
|
105
|
+
file = File.new(configfilepath,'w')
|
106
|
+
template.each_line do | line|
|
107
|
+
file.puts line
|
108
|
+
end
|
109
|
+
file.close
|
110
|
+
end
|
111
|
+
|
112
|
+
def default_config_file(override = nil)
|
113
|
+
File.expand_path(override || BASE_NAME)
|
114
|
+
end
|
115
|
+
|
116
|
+
def template
|
117
|
+
RGovData::Template.get('config_template.yml')
|
118
|
+
end
|
119
|
+
|
120
|
+
def template_path
|
121
|
+
RGovData::Template.path('config_template.yml')
|
122
|
+
end
|
123
|
+
|
124
|
+
def default_loader_options
|
125
|
+
@@default_loader_options ||= {:generate_default => false,:required => false}
|
126
|
+
end
|
127
|
+
|
128
|
+
def require_config_file
|
129
|
+
@@default_loader_options = {:generate_default => true,:required => true}
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
# Defines the default realm (country)
|
3
|
+
default_realm: sg
|
4
|
+
|
5
|
+
# Define the various credential sets that may be required
|
6
|
+
credentialsets:
|
7
|
+
# Basic authentication credentials
|
8
|
+
basic:
|
9
|
+
# ENV['rgovdata_username'] will override username if present
|
10
|
+
username: "_insert_your_username_here_"
|
11
|
+
# ENV['rgovdata_password'] will override password if present
|
12
|
+
password: "your_password"
|
13
|
+
# OData credentials for http://projectnimbus.org - APIs for Singapore Government Data
|
14
|
+
projectnimbus:
|
15
|
+
# ENV['projectnimbus_account_key'] will override AccountKey if present
|
16
|
+
AccountKey: "_insert_your_key_here_"
|
17
|
+
# ENV['projectnimbus_unique_user_id'] will override UniqueUserID if present
|
18
|
+
UniqueUserID: "00000000000000000000000000000001"
|
19
|
+
|
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:RGovData::ServiceListing
|
2
|
+
realm: :sg
|
3
|
+
key: chlkboard
|
4
|
+
name: Chlkboard
|
5
|
+
description: Information and promotion of local businesses
|
6
|
+
keywords: "F&B, retail"
|
7
|
+
publisher: Chlkboard
|
8
|
+
info_uri: http://projectnimbus.org/2010/07/17/datasets-chlkboard/
|
9
|
+
license:
|
10
|
+
uri: https://api.projectnimbus.org/chlkboardodataservice.svc
|
11
|
+
type: :odata
|
12
|
+
credentialset: projectnimbus
|
13
|
+
--- !ruby/object:RGovData::ServiceListing
|
14
|
+
realm: :sg
|
15
|
+
key: co
|
16
|
+
name: Cinema Online
|
17
|
+
description: Movie times and locations in Singapore
|
18
|
+
keywords: movie, cinema
|
19
|
+
publisher: Cinema Online
|
20
|
+
info_uri: http://projectnimbus.org/2010/04/12/datasets-cinema-online-co/
|
21
|
+
license:
|
22
|
+
uri: https://api.projectnimbus.org/coodataservice.svc
|
23
|
+
type: :odata
|
24
|
+
credentialset: projectnimbus
|
25
|
+
--- !ruby/object:RGovData::ServiceListing
|
26
|
+
realm: :sg
|
27
|
+
key: hgw
|
28
|
+
name: HungryGoWhere
|
29
|
+
description: Best food, restaurants, bars, and pubs in Singapore, Kuala Lumpur and Hong Kong
|
30
|
+
keywords: food, makan
|
31
|
+
publisher: HungryGoWhere
|
32
|
+
info_uri: http://projectnimbus.org/2010/04/11/datasets-hungrygowhere-hgw/
|
33
|
+
license:
|
34
|
+
uri: https://api.projectnimbus.org/hgwodataservice.svc
|
35
|
+
type: :odata
|
36
|
+
credentialset: projectnimbus
|
37
|
+
--- !ruby/object:RGovData::ServiceListing
|
38
|
+
realm: :sg
|
39
|
+
key: lta
|
40
|
+
name: Traffic and Road Conditions
|
41
|
+
description: Traffic and Road Conditions in Singapore
|
42
|
+
keywords: road, traffic, incidents, parking
|
43
|
+
publisher: Singapore Land Transport Authority
|
44
|
+
info_uri: http://projectnimbus.org/2010/04/05/datasets-singapore-land-transport-authority-lta/
|
45
|
+
license:
|
46
|
+
uri: https://api.projectnimbus.org/ltaodataservice.svc
|
47
|
+
type: :odata
|
48
|
+
credentialset: projectnimbus
|
49
|
+
--- !ruby/object:RGovData::ServiceListing
|
50
|
+
realm: :sg
|
51
|
+
key: nea
|
52
|
+
name: Meteorological services
|
53
|
+
description: Meteorological services in Singapore
|
54
|
+
keywords: weather
|
55
|
+
publisher: Singapore National Environment Agency
|
56
|
+
info_uri: http://projectnimbus.org/2010/04/11/datasets-singapore-national-environment-agency-nea/
|
57
|
+
license:
|
58
|
+
uri: https://api.projectnimbus.org/neaodataservice.svc
|
59
|
+
type: :odata
|
60
|
+
credentialset: projectnimbus
|
61
|
+
--- !ruby/object:RGovData::ServiceListing
|
62
|
+
realm: :sg
|
63
|
+
key: nlb
|
64
|
+
name: Libraries
|
65
|
+
description: Information about the Public Libraries in Singapore and their collections
|
66
|
+
keywords: library, book
|
67
|
+
publisher: National Library Board Singapore (NLB)
|
68
|
+
info_uri: http://projectnimbus.org/2010/04/11/datasets-national-library-board-nlb/
|
69
|
+
license:
|
70
|
+
uri: https://api.projectnimbus.org/nlbodataservice.svc
|
71
|
+
type: :odata
|
72
|
+
credentialset: projectnimbus
|
73
|
+
--- !ruby/object:RGovData::ServiceListing
|
74
|
+
realm: :sg
|
75
|
+
key: snb
|
76
|
+
name: ShowNearBy
|
77
|
+
description: locations of persons, points-of-interest, and activities
|
78
|
+
keywords: location, bus stop, ATM, clinic, shops, AED
|
79
|
+
publisher: ShowNearBy
|
80
|
+
info_uri: http://projectnimbus.org/2010/04/12/datasets-shownearby-snb/
|
81
|
+
license:
|
82
|
+
uri: https://api.projectnimbus.org/snbodataservice.svc
|
83
|
+
type: :odata
|
84
|
+
credentialset: projectnimbus
|
85
|
+
--- !ruby/object:RGovData::ServiceListing
|
86
|
+
realm: :sg
|
87
|
+
key: stb
|
88
|
+
name: Events and Places
|
89
|
+
description: Tourism related events and places
|
90
|
+
keywords: event, hotel, places of interest
|
91
|
+
publisher: Singapore Tourism Board
|
92
|
+
info_uri: http://projectnimbus.org/2010/04/12/datasets-singapore-tourism-board-stb/
|
93
|
+
license:
|
94
|
+
uri: https://api.projectnimbus.org/stbodataservice.svc
|
95
|
+
type: :odata
|
96
|
+
credentialset: projectnimbus
|
97
|
+
--- !ruby/object:RGovData::ServiceListing
|
98
|
+
realm: :sg
|
99
|
+
key: sp
|
100
|
+
name: Singapore Post
|
101
|
+
description: Post Office and SAM locations
|
102
|
+
keywords: post, location
|
103
|
+
publisher: Singapore Post
|
104
|
+
info_uri: http://projectnimbus.org/2010/04/12/datasets-singapore-post-sp/
|
105
|
+
license:
|
106
|
+
uri: https://api.projectnimbus.org/spodataservice.svc
|
107
|
+
type: :odata
|
108
|
+
credentialset: projectnimbus
|
109
|
+
--- !ruby/object:RGovData::ServiceListing
|
110
|
+
realm: :sg
|
111
|
+
key: usr
|
112
|
+
name: User Contributed Content
|
113
|
+
description: User Contributed Datasets is part of the community driven efforts to provide interesting datasets
|
114
|
+
keywords: location
|
115
|
+
publisher: ProjectNimbus
|
116
|
+
info_uri: http://projectnimbus.org/2010/10/04/datasets-user-contributed-content-usr/
|
117
|
+
license:
|
118
|
+
uri: https://api.projectnimbus.org/usrodataservice.svc
|
119
|
+
type: :odata
|
120
|
+
credentialset: projectnimbus
|
121
|
+
# --- !ruby/object:RGovData::ServiceListing
|
122
|
+
## Places currently excluded wince the metadata doesn't fully describe the mandatory parameters required
|
123
|
+
## for the Detail and Search collections. Leaving places out of the registry until this is sorted.
|
124
|
+
# realm: :sg
|
125
|
+
# key: places
|
126
|
+
# name: Places
|
127
|
+
# description: Places.sg aggregates the flow of your information to multiple web and mobile sites, so that when you upload your information and/or promotions in one place, it gets quickly syndicated to many digital properties
|
128
|
+
# keywords: location
|
129
|
+
# publisher: Places.sg
|
130
|
+
# info_uri: http://projectnimbus.org/2010/10/18/datasets-places-sg/
|
131
|
+
# license:
|
132
|
+
# uri: https://api.projectnimbus.org/placesodataservice.svc
|
133
|
+
# type: :odata
|
134
|
+
# credentialset: projectnimbus
|
135
|
+
--- !ruby/object:RGovData::ServiceListing
|
136
|
+
realm: :sg
|
137
|
+
key: caas_air_cargo_discharged
|
138
|
+
name: Air Cargo Discharged
|
139
|
+
description: Air Cargo Discharged - Total by Region and Selected Country of Origin
|
140
|
+
keywords: Transportation and Storage
|
141
|
+
publisher: Civil Aviation Authority of Singapore
|
142
|
+
info_uri:
|
143
|
+
license:
|
144
|
+
uri: http://data.gov.sg/common/download.aspx?id=13008&rid=1805010000000004396B&filetype=csv
|
145
|
+
type: :file
|
146
|
+
|
147
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
# This is a convenience class for accessing disk-based template files
|
4
|
+
# It avoids pathname processing from being required where template are used
|
5
|
+
class RGovData::Template
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# Returns the template file path
|
9
|
+
# +name+ is the filename
|
10
|
+
# +realm+ if specified is the subdirectory
|
11
|
+
def path(name, realm = nil)
|
12
|
+
extra_path = [realm,name].compact.map(&:to_s)
|
13
|
+
Pathname.new(File.dirname(__FILE__)).join(*extra_path).to_s
|
14
|
+
rescue
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the template file content
|
19
|
+
# +name+ is the filename
|
20
|
+
# +realm+ if specified is the subdirectory
|
21
|
+
def get(name, realm = nil)
|
22
|
+
IO.read(path(name, realm))
|
23
|
+
rescue
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|