Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions lib/coursemology/polyglot/concrete_language/class_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,26 @@
# This is deliberately defined so that consumers of this library can inject methods into all
# concrete languages' classes.
module Coursemology::Polyglot::ConcreteLanguage::ClassMethods
# The default algorithm for translating a language to a corresponding Docker image name.
#
# This will:
# 1. Strip the +Coursemology::Polyglot::Language+ prefix.
# 2. Underscore the name.
# 3. Replace *n*Point*n* strings with dots (e.g. Python2Point7 to Python2.7).
# 4. Replace slashes with dashes.
def docker_image
# Remove the Coursemology::Polyglot::Language prefix
class_name = name
class_name = class_name.sub(/^Coursemology::Polyglot::Language::/, '')

# Use the underscored name
class_name = class_name.underscore

# Replace the "_point" string with a decimal
class_name.gsub!(/(?<=[\d])_point(?=[\d])/, '.')

# Replace slashes with dashes
class_name.tr!('/', '-')
class_name
end
end
9 changes: 5 additions & 4 deletions lib/coursemology/polyglot/language.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@ class Coursemology::Polyglot::Language
# Concrete languages can be instantiated and used.
#
# @param [String] display_name The display name for the language
def self.concrete_language(display_name)
# @param [String] docker_image The Docker image to use for the given language. This defaults to
# the string generated by +Coursemology::Polyglot::ConcreteLanguage.docker_image+.
def self.concrete_language(display_name, docker_image: nil)
include Coursemology::Polyglot::ConcreteLanguage
extend Coursemology::Polyglot::ConcreteLanguage::ClassMethods

concrete_class_methods = Module.new do
define_method(:display_name) do
display_name
end
define_method(:display_name) { display_name }
define_method(:docker_image) { docker_image } if docker_image
end

extend concrete_class_methods
Expand Down
43 changes: 43 additions & 0 deletions spec/coursemology/polyglot/concrete_language_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
require 'spec_helper'

RSpec.describe Coursemology::Polyglot::ConcreteLanguage do
class self::DummyLanguage < Coursemology::Polyglot::Language
concrete_language 'Dummy Concrete Language'
end

class self::DummyOverriddenNameLanguage < self::DummyLanguage
concrete_language 'Dummy Overridden Concrete Language'

def self.name
'Coursemology::Polyglot::Language::Dummy::OverriddenNameLanguage'.freeze
end
end

describe '.docker_image' do
it 'removes the Coursemology::Polyglot::Language prefix' do
expect(self.class::DummyOverriddenNameLanguage.docker_image).to \
start_with('dummy')
end

it 'preserves the nesting of namespaces' do
expect(self.class::DummyOverriddenNameLanguage.docker_image).to \
eq('dummy-overridden_name_language')
end

context 'when the name contains Point surrounded by numerals' do
class self::DummyLanguage1Point0 < self::DummyLanguage; end

it 'converts "Point" to dots' do
expect(self.class::DummyLanguage1Point0.docker_image).to end_with('dummy_language1.0')
end
end

context 'when the name contains Point but not surrounded by numerals' do
class self::DummyLanguagePoint < self::DummyLanguage; end

it 'preserves "Point"' do
expect(self.class::DummyLanguagePoint.docker_image).to end_with('dummy_language_point')
end
end
end
end
19 changes: 19 additions & 0 deletions spec/coursemology/polyglot/language_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ class self::DummyLanguage < self::AbstractLanguage
concrete_language DISPLAY_NAME
end

class self::DummyLanguageWithDockerImage < self::DummyLanguage
DOCKER_IMAGE = 'dummy-docker'
concrete_language 'Dummy Docker Image Language', docker_image: DOCKER_IMAGE
end

describe '.concrete_language' do
it 'sets the correct display name' do
expect(self.class::DummyLanguage.display_name).to eq(self.class::DummyLanguage::DISPLAY_NAME)
Expand All @@ -23,6 +28,20 @@ class self::DummyLanguage < self::AbstractLanguage
expect(self.class::DummyLanguage).to \
be_a_kind_of(Coursemology::Polyglot::ConcreteLanguage::ClassMethods)
end

context 'when an explicit Docker image name is specified' do
it 'returns the explicit image name' do
expect(self.class::DummyLanguageWithDockerImage.docker_image).to \
eq(self.class::DummyLanguageWithDockerImage::DOCKER_IMAGE)
end
end

context 'when no explicit Docker image is specified' do
it 'generates an image name' do
expect(self.class::DummyLanguage.docker_image).to \
eq('r_spec-example_groups-coursemology_polyglot_language-dummy_language')
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent the first parameter one step more than the start of the previous line.

end
end
end

describe '.concrete_languages' do
Expand Down