Skip to content

Instantly share code, notes, and snippets.

@LucoLe
Forked from JohnBDonner/_coding_challenge.md
Last active August 9, 2017 11:50
Show Gist options
  • Save LucoLe/610020325cf95a114c70cf4579bce629 to your computer and use it in GitHub Desktop.
Save LucoLe/610020325cf95a114c70cf4579bce629 to your computer and use it in GitHub Desktop.
Coding Challenge

Description

Imagine we have a book model and chapter model. Both models have attributes that needs to have sanitized html. We use a gem called sanitizer to sanitize the text. Now how would you refactor this code to be more DRY and scalable? Bonus: How would you test this?

Directions:

  • Clone the gist
  • Modify the code (change these files or add your own)
  • Save your modifications as a forked gist
  • Respond to the Breezy email with a link to your gist
require 'sanitize_wrapper'
# The require statements can be moved to ApplicationRecord class if we need to perform this
# sanitization for every model that we have, but for the moment I prefer to explicitly load it
# in the models where it's needed.
class Book < ApplicationRecord
attribute :about_the_book, :string
before_validation SanitizeWrapper.new('about_the_book')
end
describe Book do
subject { described_class.new(about_the_book: about_the_book) }
context '#before_validation allows link tags for' do
let(:about_the_book) { '<a href="#">Test</a>' }
it 'about_the_book attribute' do
expect(subject.about_the_book).to eq('<a href="#" rel="nofollow">Test</a>')
end
end
context '#before_validation does not allow img tags for' do
let(:about_the_book) { 'test <img src="test.jpg"/>' }
it 'about_the_book attribute' do
expect(subject.about_the_book).to eq('test')
end
end
end
require 'sanitize_wrapper'
class Chapter < ApplicationRecord
attribute :content, :string
before_validation SanitizeWrapper.new('content')
end
describe Chapter do
subject { described_class.new(content: content) }
context '#before_validation allows link tags for' do
let(:content) { '<a href="#">Test</a>' }
it 'content attribute' do
expect(subject.content).to eq('<a href="#" rel="nofollow">Test</a>')
end
end
context '#before_validation does not allow img tags for' do
let(:content) { 'test <img src="test.jpg"/>' }
it 'content attribute' do
expect(subject.content).to eq('test')
end
end
end
# This is standart way of implementing callback object wrappers according to the Rails documentation
# http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
require 'sanitize'
class SanitizeWrapper
SANITIZE_CONFIG = Sanitize::Config::BASIC.merge output_encoding: "UTF-8"
def initialize(attribute)
@attribute = attribute
end
def before_validation(record)
record.send("#{@attribute}=", Sanitize.fragment(record.send("#{@attribute}"), SANITIZE_CONFIG))
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment