Rails String Интерполяция в строке из базы данных

Итак, вот моя проблема.

Я хочу получить строку, хранящуюся в модели, и во время выполнения изменить ее часть с помощью переменной из приложения rails. Вот пример:

У меня есть модель сообщений, которую я использую для хранения нескольких уникальных сообщений. Поэтому разные пользователи имеют одно и то же сообщение, но я хочу, чтобы они отображали свое имя в середине сообщения, например,

"Hi #{user.name}, ...."

Я попытался точно сохранить это в базе данных, но он будет экранирован перед показом в представлении или будет интерполирован при хранении в базе данных через консоль rails.

Спасибо заранее.

Ответ 1

Если вы хотите

"Hi #{user.name}, ...."

в вашей базе данных, используйте одинарные кавычки или выйдите из # с обратной косой чертой, чтобы Ruby не смог сразу преобразовать содержимое #{}:

s = 'Hi #{user.name}, ....'
s = "Hi \#{user.name}, ...."

Затем, позже, когда вы захотите сделать интерполяцию, вы могли бы, если бы вы смели или доверяли себе, используйте eval:

s   = pull_the_string_from_the_database
msg = eval '"' + s + '"'

Обратите внимание, что вам нужно будет превратить s в строку с двойными кавычками, чтобы работать eval. Это будет работать, но это не самый приятный подход, и вы откроете для себя всевозможные странные и запутанные ошибки, но все должно быть хорошо, если вы (или другие доверенные люди) пишете строки; Я думаю, вам будет лучше с простой системой микро-шаблонов, даже с такой простой:

def fill_in(template, data)
    template.gsub(/\{\{(\w+)\}\}/) { data[$1.to_sym] }
end
#...
fill_in('Hi {{user_name}}, ....', :user_name => 'Pancakes')

Вы можете использовать любые разделители, которые вы хотели, я пошел с {{...}}, потому что в последнее время я использую Mustache.js и Handlebars.js. У этой наивной реализации есть проблемы (нет параметров форматирования в шаблоне, без разграничения,...), но этого может быть достаточно; если ваши шаблоны усложняются, вы можете просто сохранить в базе данных бит ERB и использовать процессор ERB в стандартной библиотеке справиться с этим.

Ответ 2

Я не вижу причины для определения настраиваемых вспомогательных функций. Ruby предлагает очень красивые подходы к форматированию, например:

"Hello %s" % ['world']

или

"Hello %{subject}" % { subject: 'world' }

Оба примера возвращают "Hello world".

Ответ 3

В один прекрасный момент я могу подумать, что это сделать, например, для хранения шаблонов:

"привет имя"

то есть функция в моделях, которая просто заменяет теги шаблона (имя) переданными аргументами. Он также может быть Пользователем, который вошел в систему.

Поскольку эта новая функция будет частью модели, вы можете использовать ее как просто другое поле модели из любого места в рельсах, включая файл html.erb.

Надеюсь, что это поможет, дайте мне знать, если вам нужно больше описания.

Ответ 4

Добавление другого возможного решения с помощью Procs:

#String can be stored in the database
string = "->(user){ 'Hello ' + user.name}"

proc = eval(string)

proc.call(User.find(1)) #=> "Hello Bob"