Class: Nice::Recruitment::Client

Inherits:
Object
  • Object
show all
Includes:
HTTParty
Defined in:
lib/nice/recruitment/client.rb

Overview

Client for recrutement.nicecotedazur.org (Eqwa ATS).

The platform exposes no public API or feed, so offers are read from the server-rendered pages: the listing page carries every current offer in a single response, and detail pages carry the full field set. Filtered search replays the site's own form flow (CSRF-protected POST followed by a session-scoped redirect).

Constant Summary collapse

LISTING_PATH =
'/front-jobs.html'.freeze
DETAIL_PATH =
'/front-jobs-detail.html'.freeze
'__Secure-CSRFP-Token'.freeze
ENTITIES =

id_identite values wired to the entity tiles by front-jobs.js.

{
  1 => "Métropole Nice Côte d'Azur",
  2 => 'CCAS de Nice',
  3 => 'Ville de Nice'
}.freeze
DETAIL_LABELS =

Normalized French

labels on the detail page => JobOffer attributes.

{
  'référence' => 'reference',
  'contrat' => 'contract',
  'collectivité' => 'organization',
  'direction' => 'department',
  'localisation' => 'location',
  'lieu de travail' => 'workplace',
  'filière' => 'sector',
  'domaine' => 'domain',
  'catégorie' => 'category',
  "cadre d'emploi" => 'employment_framework',
  "cadre d'emplois" => 'employment_framework',
  'date limite' => 'deadline'
}.freeze

Instance Method Summary collapse

Instance Method Details

#job(id) ⇒ Object

Get a fully populated offer from its detail page.



74
75
76
77
78
# File 'lib/nice/recruitment/client.rb', line 74

def job(id)
  validate_id!(id)
  response = self.class.get(DETAIL_PATH, query: { id_job: id, id_origin: 0 }, headers: headers)
  handle_response(response) { |html| parse_detail(html, id.to_i) }
end

#jobs(keywords: nil, domain: nil, function: nil, contracts: [], sectors: [], categories: [], entity: nil) ⇒ Object

List current job offers. Without filters this is a single stateless GET returning every offer. Filters accept ids or exact labels (see #search_options): keywords (String), domain, function (requires domain), entity, and the multi-valued contracts, sectors, categories.



58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/nice/recruitment/client.rb', line 58

def jobs(keywords: nil, domain: nil, function: nil, contracts: [], sectors: [], categories: [], entity: nil)
  filters = {
    'keywords' => keywords,
    'domain' => domain,
    'function' => function,
    'contracts' => Array(contracts),
    'sectors' => Array(sectors),
    'categories' => Array(categories),
    'entity' => entity
  }
  return all_jobs if filters.values.all? { |v| v.nil? || (v.is_a?(Array) && v.empty?) }

  filtered_jobs(filters)
end

#search_optionsObject

Available filter vocabularies, parsed from the listing page: { domains: => label, functions: => {id => label}, contracts:, sectors:, categories:, entities: }.



83
84
85
86
# File 'lib/nice/recruitment/client.rb', line 83

def search_options
  response = self.class.get(LISTING_PATH, headers: headers)
  handle_response(response) { |html| parse_search_options(html) }
end