Skip to content

Commit dae34fc

Browse files
committed
feat: Enhance Couchbase initialization and add hotel API endpoints
- Improved Couchbase initialization with error handling for misconfigurations. - Added new API endpoints for hotel autocomplete and filtering in Swagger documentation. - Updated Swagger server URL to a more generic format.
1 parent 14cae5b commit dae34fc

File tree

3 files changed

+154
-76
lines changed

3 files changed

+154
-76
lines changed

config/initializers/couchbase.rb

Lines changed: 79 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,78 +6,91 @@
66
DB_CONN_STR = ENV['DB_CONN_STR']
77
DB_BUCKET_NAME = 'travel-sample' # Hardcoded bucket name
88

9-
# Check if running in CI environment
10-
if ENV['CI']
11-
# Use environment variables from GitHub Secrets
12-
options = Couchbase::Cluster::ClusterOptions.new
13-
options.authenticate(DB_USERNAME, DB_PASSWORD)
14-
COUCHBASE_CLUSTER = Couchbase::Cluster.connect(DB_CONN_STR, options)
15-
else
16-
# Load environment variables from dev.env file
17-
require 'dotenv'
18-
Dotenv.load('dev.env')
9+
begin
10+
# Check if running in CI environment
11+
if ENV['CI']
12+
# Use environment variables from GitHub Secrets
13+
options = Couchbase::Cluster::ClusterOptions.new
14+
options.authenticate(DB_USERNAME, DB_PASSWORD)
15+
COUCHBASE_CLUSTER = Couchbase::Cluster.connect(DB_CONN_STR, options)
16+
else
17+
# Load environment variables from dev.env file
18+
require 'dotenv'
19+
Dotenv.load('dev.env')
1920

20-
# Define default values
21-
DEFAULT_DB_USERNAME = 'Administrator'
22-
DEFAULT_DB_PASSWORD = 'password'
23-
DEFAULT_DB_CONN_STR = 'couchbase://localhost'
21+
# Define default values
22+
DEFAULT_DB_USERNAME = 'Administrator'
23+
DEFAULT_DB_PASSWORD = 'password'
24+
DEFAULT_DB_CONN_STR = 'couchbase://localhost'
2425

25-
# Get environment variables with fallback to default values
26-
DB_USERNAME = ENV.fetch('DB_USERNAME', DEFAULT_DB_USERNAME)
27-
DB_PASSWORD = ENV.fetch('DB_PASSWORD', DEFAULT_DB_PASSWORD)
28-
DB_CONN_STR = ENV.fetch('DB_CONN_STR', DEFAULT_DB_CONN_STR)
26+
# Get environment variables with fallback to default values
27+
DB_USERNAME = ENV.fetch('DB_USERNAME', DEFAULT_DB_USERNAME)
28+
DB_PASSWORD = ENV.fetch('DB_PASSWORD', DEFAULT_DB_PASSWORD)
29+
DB_CONN_STR = ENV.fetch('DB_CONN_STR', DEFAULT_DB_CONN_STR)
2930

30-
# Connect to the Couchbase cluster
31-
options = Couchbase::Cluster::ClusterOptions.new
32-
options.authenticate(DB_USERNAME, DB_PASSWORD)
33-
COUCHBASE_CLUSTER = Couchbase::Cluster.connect(DB_CONN_STR, options)
34-
end
31+
# Connect to the Couchbase cluster
32+
options = Couchbase::Cluster::ClusterOptions.new
33+
options.authenticate(DB_USERNAME, DB_PASSWORD)
34+
COUCHBASE_CLUSTER = Couchbase::Cluster.connect(DB_CONN_STR, options)
35+
end
3536

36-
# Open the bucket
37-
bucket = COUCHBASE_CLUSTER.bucket(DB_BUCKET_NAME)
37+
# Open the bucket
38+
bucket = COUCHBASE_CLUSTER.bucket(DB_BUCKET_NAME)
3839

39-
# Open the default collection
40-
default_collection = bucket.default_collection
40+
# Open the default collection
41+
default_collection = bucket.default_collection
4142

42-
# Create scope and collections if they don't exist
43-
begin
44-
scope = bucket.scope('inventory')
45-
rescue Couchbase::Error::ScopeNotFoundError
46-
bucket.create_scope('inventory')
47-
scope = bucket.scope('inventory')
48-
end
43+
# Create scope and collections if they don't exist
44+
begin
45+
scope = bucket.scope('inventory')
46+
rescue Couchbase::Error::ScopeNotFoundError
47+
bucket.create_scope('inventory')
48+
scope = bucket.scope('inventory')
49+
end
4950

50-
begin
51-
# create hotel search index
52-
index_file_path = 'hotel_search_index.json'
53-
index_content = File.read(index_file_path)
54-
index_data = JSON.parse(index_content)
55-
name = index_data["name"]
56-
index = Couchbase::Management::SearchIndex.new
57-
index.name= index_data["name"]
58-
index.type= index_data["type"]
59-
index.uuid= index_data["uuid"] if index_data.has_key?("uuid")
60-
index.params= index_data["params"] if index_data.has_key?("params")
61-
index.source_name= index_data["sourceName"] if index_data.has_key?("sourceName")
62-
index.source_type= index_data["sourceType"] if index_data.has_key?("sourceType")
63-
index.source_uuid= index_data["sourceUUID"] if index_data.has_key?("sourceUUID")
64-
index.source_params= index_data["sourceParams"] if index_data.has_key?("sourceParams")
65-
index.plan_params= index_data["planParams"] if index_data.has_key?("planParams")
66-
scope.search_indexes.upsert_index(index)
67-
rescue StandardError => err
68-
#puts err.full_message
69-
end
51+
begin
52+
# create hotel search index
53+
index_file_path = 'hotel_search_index.json'
54+
index_content = File.read(index_file_path)
55+
index_data = JSON.parse(index_content)
56+
name = index_data["name"]
57+
index = Couchbase::Management::SearchIndex.new
58+
index.name= index_data["name"]
59+
index.type= index_data["type"]
60+
index.uuid= index_data["uuid"] if index_data.has_key?("uuid")
61+
index.params= index_data["params"] if index_data.has_key?("params")
62+
index.source_name= index_data["sourceName"] if index_data.has_key?("sourceName")
63+
index.source_type= index_data["sourceType"] if index_data.has_key?("sourceType")
64+
index.source_uuid= index_data["sourceUUID"] if index_data.has_key?("sourceUUID")
65+
index.source_params= index_data["sourceParams"] if index_data.has_key?("sourceParams")
66+
index.plan_params= index_data["planParams"] if index_data.has_key?("planParams")
67+
scope.search_indexes.upsert_index(index)
68+
rescue StandardError => err
69+
#puts err.full_message
70+
end
7071

71-
%w[airline airport route].each do |collection_name|
72-
scope.collection(collection_name)
73-
rescue Couchbase::Error::CollectionNotFoundError
74-
scope.create_collection(collection_name)
75-
end
72+
%w[airline airport route].each do |collection_name|
73+
scope.collection(collection_name)
74+
rescue Couchbase::Error::CollectionNotFoundError
75+
scope.create_collection(collection_name)
76+
end
7677

77-
# Scope is declared as constant to run FTS queries
78-
INVENTORY_SCOPE = scope
79-
INDEX_NAME = name
80-
AIRLINE_COLLECTION = INVENTORY_SCOPE.collection('airline')
81-
AIRPORT_COLLECTION = INVENTORY_SCOPE.collection('airport')
82-
ROUTE_COLLECTION = INVENTORY_SCOPE.collection('route')
83-
HOTEL_COLLECTION = INVENTORY_SCOPE.collection('hotel')
78+
# Scope is declared as constant to run FTS queries
79+
INVENTORY_SCOPE = scope
80+
INDEX_NAME = name
81+
AIRLINE_COLLECTION = INVENTORY_SCOPE.collection('airline')
82+
AIRPORT_COLLECTION = INVENTORY_SCOPE.collection('airport')
83+
ROUTE_COLLECTION = INVENTORY_SCOPE.collection('route')
84+
HOTEL_COLLECTION = INVENTORY_SCOPE.collection('hotel')
85+
rescue StandardError => err
86+
# Allow Rails to boot even if Couchbase is not reachable/misconfigured
87+
warn_msg = "Couchbase initialization skipped: #{err.class}: #{err.message}"
88+
defined?(Rails) ? Rails.logger.warn(warn_msg) : warn(warn_msg)
89+
COUCHBASE_CLUSTER = nil
90+
INVENTORY_SCOPE = nil
91+
INDEX_NAME = nil
92+
AIRLINE_COLLECTION = nil
93+
AIRPORT_COLLECTION = nil
94+
ROUTE_COLLECTION = nil
95+
HOTEL_COLLECTION = nil
96+
end

spec/swagger_helper.rb

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,7 @@
2525
paths: {},
2626
servers: [
2727
{
28-
url: 'http://{defaultHost}',
29-
variables: {
30-
defaultHost: {
31-
default: 'localhost:3000'
32-
}
33-
}
28+
url: '/'
3429
}
3530
],
3631
components: {

swagger/v1/swagger.yaml

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,79 @@ paths:
441441
type: string
442442
'400':
443443
description: bad request
444+
"/api/v1/hotels/autocomplete":
445+
get:
446+
summary: Retrieve suggestion for Hotel names
447+
tags:
448+
- Hotels
449+
parameters:
450+
- name: name
451+
in: query
452+
description: name of the hotel
453+
schema:
454+
type: string
455+
responses:
456+
'200':
457+
description: No suggestion
458+
content:
459+
application/json:
460+
schema:
461+
type: Array
462+
items:
463+
type: string
464+
"/api/v1/hotels/filter":
465+
post:
466+
summary: Hotel search filter
467+
tags:
468+
- Hotels
469+
parameters: []
470+
responses:
471+
'200':
472+
description: only one Hotels found
473+
content:
474+
application/json:
475+
schema:
476+
type: Array
477+
items:
478+
type: object
479+
properties:
480+
name:
481+
type: string
482+
title:
483+
type: string
484+
description:
485+
type: string
486+
country:
487+
type: string
488+
city:
489+
type: string
490+
nullable: true
491+
state:
492+
type: string
493+
nullable: true
494+
required:
495+
- name
496+
- title
497+
- description
498+
requestBody:
499+
content:
500+
application/json:
501+
schema:
502+
type: object
503+
properties:
504+
name:
505+
type: string
506+
title:
507+
type: string
508+
description:
509+
type: string
510+
country:
511+
type: string
512+
city:
513+
type: string
514+
state:
515+
type: string
516+
description: hotel filter
444517
"/api/v1/routes/{id}":
445518
get:
446519
summary: Retrieves a route by ID
@@ -619,10 +692,7 @@ paths:
619692
'404':
620693
description: route not found
621694
servers:
622-
- url: http://{defaultHost}
623-
variables:
624-
defaultHost:
625-
default: localhost:3000
695+
- url: "/"
626696
components:
627697
schemas:
628698
Airline:

0 commit comments

Comments
 (0)