На самом деле это одно и то же. DSL, как правило, реализуются с помощью обычных языковых механизмов в Ruby, поэтому технически они все API.
Однако, чтобы люди распознавали что-то как DSL, обычно заканчивалось добавлением в существующие классы декларативных операторов. Что-то вроде валидаторов и объявлений отношений в ActiveRecord.
class Foo << ActiveRecord::Base
validates_uniqueness_of :name
validates_numericality_of :number, :integer_only => true
end
выглядит как DSL, а следующее - нет:
class Foo <<ActiveRecord::BAse
def validate
unless unique? name
errors.add(:name, "must be unique")
end
unless number.to_s.match?(/^[-]?\d$/)
errors.add(:number, "must be an integer")
end
end
end
Они оба будут реализованы с помощью обычного кода Ruby. Просто один выглядит так, будто у вас есть новые классные языковые конструкции, а другой кажется довольно пешеходным (и слишком многословным и т. Д.