Skip to content

Instantly share code, notes, and snippets.

@benhawker
Last active April 8, 2016 07:06
Show Gist options
  • Save benhawker/1d2f8cac88befcbaf7f8a1e687047335 to your computer and use it in GitHub Desktop.
Save benhawker/1d2f8cac88befcbaf7f8a1e687047335 to your computer and use it in GitHub Desktop.
Automatic Description Generator - Rails Service Class for a Property Rental Web App
module Rooms
class TitleGenerator
attr_reader :room, :locale
def initialize(room, locale="en")
@room = room
@locale = locale
end
def generate
if room_type_number_and_destination.present? && size_adjective.present? && amenities.present?
[size_adjective, room_type_number_and_destination, amenities].compact.join(" ").html_safe
elsif room_type_number_and_destination.present? && amenities.present?
[room_type_number_and_destination, amenities].compact.join(" ").html_safe
elsif room_type_number_and_destination.present? && size_adjective.present?
[size_adjective, room_type_number_and_destination].compact.join(" ").html_safe
elsif room_type_number_and_destination.present?
room_type_number_and_destination
end
end
# Shared methods
def t(key, options={})
value = I18n.t("rooms.title_generator.#{key}")
key = "#{key}.#{sample(value.keys)}" if value.is_a?(Hash)
I18n.t("rooms.title_generator.#{key}", options.merge({ locale: locale }))
end
# Translation Helpers
def room_type
@room_type ||= I18n.t("room_types.#{room.room_type.type}", locale: locale)
end
def destination
@destination ||= room.destination.name_translations[locale] || room.destination.name_translations["en"]
end
# Sentences
def size_adjective
# For properties less than 500sq ft/50 sqm
small_adjective = I18n.t("rooms.title_generator.adjectives.small", locale: locale).map{ |key, value| value }
small_adjective = small_adjective.sample
# For properties 500-1000 sq ft/ 50-100 sqm
medium_adjective = I18n.t("rooms.title_generator.adjectives.medium", locale: locale).map{ |key, value| value }
medium_adjective = medium_adjective.sample
# For properties above 1000 sf/100 sqm
large_adjective = I18n.t("rooms.title_generator.adjectives.large", locale: locale).map{ |key, value| value }
large_adjective = large_adjective.sample
if room.surface.present? && room.surface_unit.present? && room.surface_unit == "metric"
case
when room.surface >= 100 then large_adjective
when room.surface >= 50 && room.surface < 100 then medium_adjective
when room.surface < 50 then small_adjective
end
elsif room.surface.present? && room.surface_unit.present? && room.surface_unit == "imperial"
case
when room.surface >= 1000 then large_adjective
when room.surface >= 500 && room.surface < 1000 then medium_adjective
when room.surface < 500 then small_adjective
end
else
return nil
end
end
def room_type_number_and_destination
if room.destination.present? && room.number_of_rooms && room.room_type.present?
case
when room.number_of_rooms >= 1 then t("number_type_destination", room_type: room_type, number_of_rooms: room.number_of_rooms, destination: destination)
when room.number_of_rooms == 0 then t("studio_type_destination", room_type: room_type, destination: destination)
end
elsif room.room_type && room.number_of_rooms && room.neighborhood.present? && room.city.present?
case
when room.number_of_rooms >= 1 then t("number_type_neighborhood_city", room_type: room_type, number_of_rooms: room.number_of_rooms, neighborhood: room.neighborhood, city: room.city)
when room.number_of_rooms == 0 then t("studio_type_neighborhood_city", room_type: room_type, neighborhood: room.neighborhood, city: room.city)
end
elsif room.destination.present? && room.number_of_rooms
t("number_destination", number_of_rooms: room.number_of_rooms, destination: destination)
elsif room.number_of_rooms && room.room_type.present?
t("number_type", number_of_rooms: room.number_of_rooms, room_type: room_type)
else
return nil
end
end
def amenities
tmp = amenities_list
if tmp.present?
return t("amenities.with") + " " + tmp.to_sentence
else
return nil
end
end
def amenities_list
tmp = []
tmp << t("amenities.aircon") if room.airconditioning?
tmp << t("amenities.parking") if room.parking
tmp << t("amenities.pool") if room.pool
tmp << t("amenities.gym") if room.gym
tmp << t("amenities.doorman") if room.doorman
tmp << t("amenities.balcony") if room.balcony
tmp << t("amenities.breakfast_provided") if room.breakfast
tmp
end
end
end
______
require 'spec_helper'
describe Rooms::TitleGenerator do
let!(:room) { create(:room) }
let(:locale) { 'en' }
let(:generator) { Rooms::TitleGenerator.new(room, locale) }
describe "#generate" do
context "room_type_number_and_destination.present? && size_adjective.present? && amenities.present?" do
it "returns the correct title for the specified large room with some amenities" do
sentence = /(?:Family-friendly|Group-friendly|Perfect|Spacious|Large|Grand|Very|Spacious|Awesome|Wonderful|Fantastic|Amazing|Superb|Marvellous|Stunning|Incredible|Fine|Excellent|Fab|Superb) 4 Bedroom Apartment in Chinatown with Pool and Gym/
room.surface = 120
room.surface_unit = "metric"
room.number_of_rooms = 4
room.room_type.type = "Apartment"
room.destination.name = "Chinatown"
room.pool = true
room.gym = true
expect(generator.send(:generate)).to match (sentence)
end
end
context "room_type_number_and_destination.present? && amenities.present? - without size" do
it "returns the correct title for the specified room with some amenities" do
sentence = "4 Bedroom Apartment in Chinatown with Pool and Gym"
room.surface = nil
room.surface_unit = nil
room.number_of_rooms = 4
room.room_type.type = "Apartment"
room.destination.name = "Chinatown"
room.pool = true
room.gym = true
expect(generator.send(:generate)).to match (sentence)
end
end
context "room_type_number_and_destination.present? && size_adjective.present? - without amenities" do
it "returns the correct title for for the specified small room" do
sentence = /(?:Cozy|Warm|Welcoming|Compact|Comfy|Comfortable|Intimate|Agreeable|Pleasant|Delightful|Charming|Lovely|Convenient|Accessible) Studio Apartment in Chinatown/
room.surface = 40
room.surface_unit = "metric"
room.number_of_rooms = 0
room.room_type.type = "Apartment"
room.destination.name = "Chinatown"
expect(generator.send(:generate)).to match (sentence)
end
it "returns the correct title for the specified medium room" do
sentence = /(?:Comfortable|Spacious|Welcoming|Comfortable|Large|Good-sized|Lovely|Charming|Well-spaced|Well-appointed|Wonderful|Beautiful|Great|Fantastic|Super|Friendly|Amazing|Unbeatable|Awesome) 2 Bedroom Apartment in Chinatown/
room.surface = 80
room.surface_unit = "metric"
room.number_of_rooms = 2
room.room_type.type = "Apartment"
room.destination.name = "Chinatown"
expect(generator.send(:generate)).to match (sentence)
end
it "returns the correct title for the specified large room" do
sentence = /(?:Family-friendly|Group-friendly|Perfect|Spacious|Large|Grand|Very|Spacious|Awesome|Wonderful|Fantastic|Amazing|Superb|Marvellous|Stunning|Incredible|Fine|Excellent|Fab|Superb) 4 Bedroom Apartment in Chinatown/
room.surface = 120
room.surface_unit = "metric"
room.number_of_rooms = 4
room.room_type.type = "Apartment"
room.destination.name = "Chinatown"
expect(generator.send(:generate)).to match (sentence)
end
end
context "room_type_number_and_destination.present? - without size or amenities" do
it "returns the correct title for the room specified without a size" do
sentence = "4 Bedroom Apartment in Chinatown"
room.surface = nil
room.surface_unit = nil
room.number_of_rooms = 4
room.room_type.type = "Apartment"
room.destination.name = "Chinatown"
expect(generator.send(:generate)).to eq (sentence)
end
end
context "nil for required attributes" do
it "returns nil if we have no suggested title to offer" do
room.number_of_rooms = nil
room.destination = nil
room.room_type.type = nil
room.neighborhood = nil
room.city = nil
room.surface = nil
room.surface_unit = nil
expect(generator.send(:generate)).to eq nil
end
end
end
describe "#size_adjective" do
context "metric" do
it "returns one of specified adjectives for 'small' property" do
sentence = /(?:Cozy|Warm|Welcoming|Compact|Comfy|Comfortable|Intimate|Agreeable|Pleasant|Delightful|Charming|Lovely|Convenient|Accessible)/
room.surface = 40
room.surface_unit = "metric"
expect(generator.send(:size_adjective)).to match (sentence)
end
it "returns one of specified adjectives for 'medium' property" do
sentence = /(?:Comfortable|Spacious|Welcoming|Comfortable|Large|Good-sized|Lovely|Charming|Well-spaced|Well-appointed|Wonderful|Beautiful|Great|Fantastic|Super|Friendly|Amazing|Unbeatable|Awesome)/
room.surface = 80
room.surface_unit = "metric"
expect(generator.send(:size_adjective)).to match (sentence)
end
it "returns one of specified adjectives for 'large' property" do
sentence = /(?:Family-friendly|Group-friendly|Perfect|Spacious|Large|Grand|Very|Spacious|Awesome|Wonderful|Fantastic|Amazing|Superb|Marvellous|Stunning|Incredible|Fine|Excellent|Fab|Superb)/
room.surface = 120
room.surface_unit = "metric"
expect(generator.send(:size_adjective)).to match (sentence)
end
end
context "imperial" do
it "returns one of specified adjectives for 'small' property" do
sentence = /(?:Cozy|Warm|Welcoming|Compact|Comfy|Comfortable|Intimate|Agreeable|Pleasant|Delightful|Charming|Lovely|Convenient|Accessible)/
room.surface = 400
room.surface_unit = "imperial"
expect(generator.send(:size_adjective)).to match (sentence)
end
it "returns one of specified adjectives for 'medium' property" do
sentence = /(?:Comfortable|Spacious|Welcoming|Comfortable|Large|Good-sized|Lovely|Charming|Well-spaced|Well-appointed|Wonderful|Beautiful|Great|Fantastic|Super|Friendly|Amazing|Unbeatable|Awesome)/
room.surface = 800
room.surface_unit = "imperial"
expect(generator.send(:size_adjective)).to match (sentence)
end
it "returns one of specified adjectives for 'large' property" do
sentence = /(?:Family-friendly|Group-friendly|Perfect|Spacious|Large|Grand|Very|Spacious|Awesome|Wonderful|Fantastic|Amazing|Superb|Marvellous|Stunning|Incredible|Fine|Excellent|Fab|Superb)/
room.surface = 1200
room.surface_unit = "imperial"
expect(generator.send(:size_adjective)).to match (sentence)
end
end
context "no surface unit or measurement" do
it "returns nil when no surface unit or measurement is given" do
room.surface = nil
room.surface_unit = nil
expect(generator.send(:size_adjective)).to eq nil
end
end
end
describe "#room_type_number_and_destination" do
it "returns the correct title when room has destination, # of rooms and also type with many bedrooms" do
sentence = "2 Bedroom Apartment in Chinatown"
room.number_of_rooms = 2
room.room_type.type = "Apartment"
room.destination.name = "Chinatown"
expect(generator.send(:room_type_number_and_destination)).to eq (sentence)
end
it "returns the correct title when room has destination, # of rooms and also type with zero bedrooms (studio)" do
sentence = "Studio Apartment in Chinatown"
room.number_of_rooms = 0
room.room_type.type = "Apartment"
room.destination.name = "Chinatown"
expect(generator.send(:room_type_number_and_destination)).to match (sentence)
end
it "returns the correct title when room has destination, # of rooms (but no type)" do
sentence = "2 Bedroom Property in Chinatown"
room.number_of_rooms = 2
room.room_type = nil
room.destination.name = "Chinatown"
expect(generator.send(:room_type_number_and_destination)).to eq (sentence)
end
it "returns the correct title when room has number of rooms, neighborhood, city and room type" do
sentence = "2 Bedroom Apartment in Chinatown, Singapore"
room.number_of_rooms = 2
room.destination = nil
room.room_type.type = "Apartment"
room.neighborhood = "Chinatown"
room.city = "Singapore"
expect(generator.send(:room_type_number_and_destination)).to eq (sentence)
end
it "returns the correct title when room has neighborhood, city and room type with zero bedrooms (studio)" do
sentence = "Studio Apartment in Chinatown"
room.number_of_rooms = 0
room.destination = nil
room.room_type.type = "Apartment"
room.neighborhood = "Chinatown"
room.city = "Singapore"
expect(generator.send(:room_type_number_and_destination)).to match (sentence)
end
end
describe "#amenities" do
it "returns the correct sentence when room has all the specified amenities" do
sentence = "with Aircon, Parking, Pool, Gym, Doorman, Balcony, and Breakfast-provided"
room.airconditioning = true
room.parking = true
room.pool = true
room.gym = true
room.doorman = true
room.breakfast = true
room.balcony = true
expect(generator.send(:amenities)).to match (sentence)
end
it "returns the correct sentence when room has only one specified amenities" do
sentence = "with Breakfast-provided"
room.breakfast = true
expect(generator.send(:amenities)).to match (sentence)
end
it "returns the correct sentence when room has only one specified amenities" do
room.airconditioning = nil
room.parking = nil
room.pool = nil
room.gym = nil
room.doorman = nil
room.breakfast = nil
room.balcony = nil
expect(generator.send(:amenities)).to eq nil
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment