26

所以这是我的问题。

我想检索存储在模型中的字符串,并在运行时使用 rails 应用程序中的变量更改其中的一部分。这是一个例子:

我有一个 Message 模型,我用它来存储几个独特的消息。所以不同的用户有相同的消息,但我希望能够在消息中间显示他们的名字,例如,

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

我试图将它准确地存储在数据库中,但它在显示在视图中之前被转义,或者在存储在数据库中时被插值,通过 rails 控制台。

提前致谢。

4

5 回答 5

61

我看不到定义自定义字符串辅助函数的理由。Ruby 提供了非常好的格式化方法,例如:

"Hello %s" % ['world']

或者

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

这两个示例都返回“Hello world”。

于 2014-04-29T09:23:07.180 回答
22

如果你想

"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。这种幼稚的实现存在问题(没有模板内格式化选项,没有分隔符转义,......)但它可能就足够了。如果您的模板变得更复杂,那么可能会String#%ERB可能会更好。

于 2011-07-21T17:19:24.430 回答
0

我能想到的一种方法是存储模板,例如:

“你好名字”

然后在模型中有一个函数,它只是用传递的参数替换模板标签(名称)。也可以是登录的用户。

因为这个新函数将成为模型的一部分,所以您可以像在 rails 中的任何位置(包括 html.erb 文件)一样使用模型的另一个字段。

希望对您有所帮助,如果您需要更多描述,请告诉我。

于 2011-07-21T15:06:07.413 回答
0

gsub在 Ruby 中非常强大。

它将散列作为第二个参数,因此您可以为其提供要替换的键的白名单:

template = <<~STR
Hello %{user_email}!

You have %{user_voices_count} votes!

Greetings from the system
STR

template.gsub(/%{.*?}/, {
  "%{user_email}" => 'schmijos@example.com',
  "%{user_voices_count}" => 5,
  "%{release_distributable_total}" => 131,
  "%{entitlement_value}" => 2,
})

比较ERB安全。它不会抱怨单个%和未使用或不存在的键,例如使用%( sprintf) 进行的字符串插值。

于 2021-12-08T21:07:52.170 回答
0

使用 Procs 添加另一个可能的解决方案:

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

proc = eval(string)

proc.call(User.find(1)) #=> "Hello Bob"
于 2015-07-23T06:34:37.227 回答