Class: Transilien::MicroService

Inherits:
Object
  • Object
show all
Defined in:
lib/transilien/micro_service.rb

Defined Under Namespace

Classes: Error

Constant Summary collapse

API_HOST =
'ms.api.transilien.com'
API_URI =
URI.parse("http://#{API_HOST}/")
Default_cache_duration =

in second

300

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.cachesObject

Returns the value of attribute caches.



20
21
22
# File 'lib/transilien/micro_service.rb', line 20

def caches
  @caches
end

.query_cache(query = nil) ⇒ Object

Returns the value of attribute query_cache.



21
22
23
# File 'lib/transilien/micro_service.rb', line 21

def query_cache
  @query_cache
end

Instance Attribute Details

#access_timeObject

Returns the value of attribute access_time.



13
14
15
# File 'lib/transilien/micro_service.rb', line 13

def access_time
  @access_time
end

#external_codeObject

Returns the value of attribute external_code.



11
12
13
# File 'lib/transilien/micro_service.rb', line 11

def external_code
  @external_code
end

#nameObject

Returns the value of attribute name.



10
11
12
# File 'lib/transilien/micro_service.rb', line 10

def name
  @name
end

#payloadObject

Returns the value of attribute payload.



14
15
16
# File 'lib/transilien/micro_service.rb', line 14

def payload
  @payload
end

Class Method Details

.actionObject



136
137
138
# File 'lib/transilien/micro_service.rb', line 136

def action
  "#{action_component}List"
end

.action_componentObject



132
133
134
# File 'lib/transilien/micro_service.rb', line 132

def action_component
  self.to_s.split('::').last 
end

.action_instance_xpathObject



144
145
146
# File 'lib/transilien/micro_service.rb', line 144

def action_instance_xpath
  "/Action#{action}/#{action}/#{action_component}"
end

.action_paramObject



140
141
142
# File 'lib/transilien/micro_service.rb', line 140

def action_param
  "/?action=#{action}"
end

.add_filtersObject



179
180
181
# File 'lib/transilien/micro_service.rb', line 179

def add_filters()
  self.filters
end

.cache_it(item) ⇒ Object



98
99
100
101
102
103
104
105
# File 'lib/transilien/micro_service.rb', line 98

def cache_it(item)
  @caches ||= {}
  cache_keys.each do |k|
    @caches[k] ||= {}
    @caches[k][item.send(k)] = item
  end
  item
end

.cache_keysObject



94
95
96
# File 'lib/transilien/micro_service.rb', line 94

def cache_keys
  [:name, :external_code]
end

.errors(doc) ⇒ Object



117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/transilien/micro_service.rb', line 117

def errors(doc)
  @errors ||= begin 
    @errors = []
    doc.xpath('/Errors/Error').each do |err_node|
      err = Transilien::MicroService::Error.new
      err.code = err_node['code']
      err.message = err_node.content
      err.request = { params: params, action: action_param}
      @errors << err
    end
    @errors
  end
end

.filtersObject



170
171
172
# File 'lib/transilien/micro_service.rb', line 170

def filters
  @filters ||= {}
end

.filters=(new_filters) ⇒ Object

Raises:

  • (ArgumentError)


174
175
176
177
# File 'lib/transilien/micro_service.rb', line 174

def filters=(new_filters)
  raise ArgumentError.new('filters= -> new_filters MUST be a hash, even empty') unless new_filters.is_a?(Hash)
  @filters = new_filters
end

.find(filters = {}, options = {}) ⇒ Object

/?action=LineList&StopAreaExternalCode=DUA8754309;DUA8754513|and&RouteExternalCode=DUA8008030781013;DUA8008031050001|or -> find(:stop_area_external_code => { :and => [‘DUA8754309’, ‘DUA8754513’] }, :route_external_code => { :or => [‘DUA8008030781013’, ‘DUA8008031050001’] })



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/transilien/micro_service.rb', line 57

def find(filters = {}, options = {})
  collection =   find_from_full_query_cache(filters)
  collection ||= find_from_query_caches(filters)

  self.filters = filters
  response = self.http.get(action_param, params)
  puts('== Request: ')
  puts(action_param.inspect)
  puts(params.inspect)
  puts(response.env[:url].inspect)
  body = response.body
  collection = []
  doc = Nokogiri.XML(body)
  return errors(doc) unless errors(doc).empty?
  request_time = Time.parse(response.headers[:date])
  doc.xpath(action_instance_xpath).each do |node|
    item = from_node(node, request_time)
    collection << item
  end
  @query_cache[filters.to_s] = { payload: collection, cached_at: request_time }
  collection
end

.find_from_full_query_cache(filters) ⇒ Object



32
33
34
35
36
37
38
39
40
# File 'lib/transilien/micro_service.rb', line 32

def find_from_full_query_cache(filters)
  @query_cache ||= {}
  if filters[:force_refresh]
    @query_cache.delete(filters.to_s)
  end
  if @query_cache[filters.to_s] && (@query_cache[filters.to_s][:cached_at].to_i + Default_cache_duration > Time.now.to_i)
    return @query_cache[filters.to_s][:payload]
  end
end

.find_from_query_caches(filters, collection = nil, operator = nil) ⇒ Object

Iterative search on per instance search. That’s HARD. WIP idea: since filters are prefixed by operator (AND by default), we can deal key by key. Collection on the first run is the matching instances on that uniq key. The result will be the last collection returned. Potentially nil.



45
46
47
48
49
50
51
52
53
# File 'lib/transilien/micro_service.rb', line 45

def find_from_query_caches(filters, collection = nil, operator = nil)
  if collection.nil?
    # FIRST RUN
    filters.keys.each do |key|
      collection = [query_cache({key: key, value: filters[key]})]
    end
  end

end

.from_node(node, access_time) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/transilien/micro_service.rb', line 80

def from_node(node, access_time)
  item = new
  item.payload = node

  # common stuff
  item.external_code = node["#{action_component}ExternalCode"]
  item.name = node["#{action_component}Name"]
  item.access_time = access_time

  cache_it(item)

  item
end

.http(uri = API_URI) ⇒ Object



23
24
25
26
27
28
29
30
# File 'lib/transilien/micro_service.rb', line 23

def http(uri = API_URI)
  @http ||= Faraday.new(:url => uri) do |faraday|
    # TODO give option to setup faraday
    faraday.request  :url_encoded             # form-encode POST params
    #faraday.response :logger                  # log requests to STDOUT 
    faraday.adapter  Faraday.default_adapter  # make requests with Net::HTTP
  end
end

.paramsObject



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/transilien/micro_service.rb', line 148

def params
  return {} if filters.empty?
  final = {}
  @filters.each do |filter, filter_value| 
    final_filter = filter.to_s.split('_').map(&:capitalize).join
    if filter_value.is_a?(Hash)
      filter_value.each_pair do |operator, values|
        ok_operators = [:and, :or]
        raise ArgumentError.new("Operator #{operator} unknown. Should be one of #{ok_operators.inspect}.") unless ok_operators.include?(operator.to_sym)
        final_values = [values].flatten.compact.join(';')
        final[final_filter] = "#{final_values}|#{operator.to_s}"
      end
    elsif filter_value.is_a?(Array)
      # By default, consider OR operator when values are only an array
      final[final_filter] = "#{filter_value.join(';')}|or"
    else
      final[final_filter] = filter_value
    end
  end
  final
end

Instance Method Details

#to_sObject



185
186
187
# File 'lib/transilien/micro_service.rb', line 185

def to_s
  "#<#{self.class.to_s} external_code=#{@external_code.inspect} name=#{@name.inspect} >"
end