Last active
April 8, 2016 07:06
-
-
Save benhawker/1d2f8cac88befcbaf7f8a1e687047335 to your computer and use it in GitHub Desktop.
Automatic Description Generator - Rails Service Class for a Property Rental Web App
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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