Я заинтересован в создании DSL на Ruby для анализа обновлений микроблогов. В частности, я подумал, что мог бы перевести текст в строку Ruby так же, как в геме Rails разрешено "4.days.ago". У меня уже есть код регулярного выражения, который будет переводить текст
@USER_A: give X points to @USER_B for accomplishing some task
@USER_B: take Y points from @USER_A for not giving me enough points
в нечто вроде
Scorekeeper.new.give(x).to("USER_B").for("accomplishing some task").giver("USER_A")
Scorekeeper.new.take(x).from("USER_A").for("not giving me enough points").giver("USER_B")
Для меня приемлемо формализовать синтаксис обновлений так, чтобы был предоставлен и проанализирован только стандартизированный текст, что позволяет мне грамотно обрабатывать обновления. Таким образом, кажется, это больше вопрос о том, как реализовать класс DSL. У меня есть следующий класс заглушки (убрал все проверки ошибок и заменил некоторые комментарии, чтобы минимизировать вставку):
class Scorekeeper
attr_accessor :score, :user, :reason, :sender
def give(num)
# Can 'give 4' or can 'give a -5'; ensure 'to' called
self.score = num
self
end
def take(num)
# ensure negative and 'from' called
self.score = num < 0 ? num : num * -1
self
end
def plus
self.score > 0
end
def to (str)
self.user = str
self
end
def from(str)
self.user = str
self
end
def for(str)
self.reason = str
self
end
def giver(str)
self.sender = str
self
end
def command
str = plus ? "giving @#{user} #{score} points" : "taking #{score * -1} points from @#{user}"
"@#{sender} is #{str} for #{reason}"
end
end
Выполнение следующих команд:
t = eval('Scorekeeper.new.take(4).from("USER_A").for("not giving me enough points").giver("USER_B")')
p t.command
p t.inspect
Дает ожидаемые результаты:
"@USER_B is taking 4 points from @USER_A for not giving me enough points"
"#<Scorekeeper:0x100152010 @reason=\"not giving me enough points\", @user=\"USER_A\", @score=4, @sender=\"USER_B\">"
Так что мой вопрос в основном таков: делаю ли я что-нибудь, чтобы выстрелить себе в ногу, опираясь на эту реализацию? У кого-нибудь есть примеры улучшения в самом классе DSL или какие-либо предупреждения для меня?
Кстати, чтобы получить строку eval, я в основном использую sub / gsub и regex, я подумал, что это самый простой способ, но я могу ошибаться.