Class: Nice::Recruitment::Client
- Inherits:
-
Object
- Object
- Nice::Recruitment::Client
- 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
- CSRF_COOKIE =
The CSRF token must be posted back in a form field named after the cookie itself (the site's csrfprotector.js overrides the field name with the value of #csrfp_hidden_data_token). A wrong or missing token makes the server silently ignore the filters.
'__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
-
#job(id) ⇒ Object
Get a fully populated offer from its detail page.
-
#jobs(keywords: nil, domain: nil, function: nil, contracts: [], sectors: [], categories: [], entity: nil) ⇒ Object
List current job offers.
-
#search_options ⇒ Object
Available filter vocabularies, parsed from the listing page: { domains: => label, functions: => {id => label}, contracts:, sectors:, categories:, entities: }.
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_options ⇒ Object
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 response = self.class.get(LISTING_PATH, headers: headers) handle_response(response) { |html| (html) } end |