Rails String Интерполяция в строку из базы данных - PullRequest
18 голосов
/ 21 июля 2011

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

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

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

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

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

Заранее спасибо.

Ответы [ 4 ]

48 голосов
/ 29 апреля 2014

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

"Hello %s" % ['world']

или

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

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

18 голосов
/ 21 июля 2011

Если хотите

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

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

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

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

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

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

Я думаю, вам лучше использовать простую систему микро-шаблонов, даже такую ​​простую, как эта:

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. Эта наивная реализация имеет проблемы (без параметров форматирования в шаблоне, без экранирования, ...), но этого может быть достаточно. Если ваши шаблоны усложняются, возможно, String#% или ERB могут работать лучше.

0 голосов
/ 23 июля 2015

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

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

proc = eval(string)

proc.call(User.find(1)) #=> "Hello Bob"
0 голосов
/ 21 июля 2011

Один из способов сделать это - хранить шаблоны, например:

"привет, имя"

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...