2011-07-21 22 views
11

İşte benim problemim.Raylar String Bir dizgeden bir dizgede enterpolasyon

Modelde depolanmış bir dize almak istiyorum ve çalışma zamanında raylar uygulamasından bir değişken kullanarak bir parçasını değiştirin. İşte bir örnek:

Birkaç benzersiz mesajı saklamak için kullandığım bir Message modelim var. Yani farklı kullanıcıların aynı mesajı var, ama mesajın, örneğin ortasında isimlerini göstermek isterler,

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

ben veritabanında tam olarak saklamak için çalıştık ama gösterilmeden önce kaçan alır raylar konsolu üzerinden veritabanında saklanırken görünüm veya enterpolasyonlu olur.

Şimdiden teşekkürler. Bunu yaparken düşünebilirsiniz

cevap

9

hemen #{} şeyler interpolating gelen Ruby tutmak için tek tırnak kullanmak veya ters eğik çizgi # kaçış Kendinizi cesaretlendirdiyseniz veya kendinize güvenirseniz, enterpolasyon yapmak istiyorsanız, eval:

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

eval'un çalışması için s çift tırnak içine alın. Bu işe yarayacak, ama bu en güzel yaklaşım değil ve her türlü garip ve kafa karıştırıcı hatalara açık bırakıyor ama siz (ya da diğer güvenilir insanlar) dizeleri yazdığınız sürece her şey yolunda olmalıdır; Ben basit bir mikro şablon sisteminin bu kadar basit bile bir şey ile daha iyi olurdu düşünüyorum:

def fill_in(template, data) 
    template.gsub(/\{\{(\w+)\}\}/) { data[$1.to_sym] } 
end 
#... 
fill_in('Hi {{user_name}}, ....', :user_name => 'Pancakes') 
Sen elbette istediğini sınırlayıcı kullanabilirsiniz

ben kullanıyorum çünkü ben {{...}} gitti Son zamanlarda Mustache.js ve Handlebars.js. Bu naif uygulamanın sorunları var (şablon formatlama seçenekleri yok, sınırlayıcı yok, ...) ama yeterli olabilir; Eğer şablonlarınız daha karmaşık hale gelirse, o zaman veritabanında ERB bitlerini saklamak ve ERB işlemciyi standart kütüphane anlaşmasında kullanmak isteyebilirsiniz.

+0

Teşekkürler, işe yaradı ... Zaten tek tırnaklı dizeyi saklıyordum. Veritabanından aldıktan sonra nasıl interpolasyon yapılacağı konusunda eksik kaldım. Bunu kullanarak güvenlik riskinin farkındayım, ancak kullanıcılar bu dizeyi doğrudan değiştiremez. –

+0

Dize içeriğiniz HTML içeriyorsa 'raw' (http://apidock.com/rails/ActionView/Helpers/OutputSafetyHelper/raw) yöntemini 'html_safe' yöntemine göre kullanacağım. – dennismonsewicz

0

tek yön örneğin saklanan şablonları sahip olmaktır:

"Merhaba adı"

sonra sadece geçmiş ile şablon etiketlerini (isim) yerini modellerinde bir işlevi var argümanlar. Ayrıca oturum açan kullanıcı da olabilir.

Bu yeni işlev modelin bir parçası olacağından, html.erb dosyası dahil olmak üzere rayların herhangi bir yerinden başka bir model alanı gibi kullanabilirsiniz.

Daha fazla açıklamaya ihtiyacınız varsa bana yardımcı olur umarım.

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

Sonra daha sonra zaman: veritabanınızda

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

istiyorsanız

+0

, bu gördüğünüz Sorun tüm olası etiketlerini tanımlamak zorunda kalacak kullandığım ve her harita olabilir ki Biri uygulama içindeki ilgili değişkenlere/fonksiyonlara. Sadece normal bir dizge için enterpolasyon gibi, bunu yapmanın daha basit bir yolu olacağını düşündüm. –

+0

Bence yaklaşımınız da işe yarayacak. Çift tırnak yerine tek tırnak kullanarak dizgi oluşturarak veritabanında saklanmadan önce enterpolasyon oluşturduğunuz dizeden kaçınabilirsiniz. Görmeye gelmeden önce neden kaçtığından emin değilim. – Shaunak

+0

Tek tırnaklı sürümü saklıyordum, ancak veritabanına kaydetmeden önce kaçan çift tırnaklı bir dizgeye dönüşüyor. –

34

Özel dize yardımcı işlevleri tanımlamak için bir neden göremiyorum. Ruby, very nice formatting approaches, ör.:

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

Hem örnekler

"Hello %s" % ['world'] 

veya

"Merhaba dünya" dönün.

+5

Bu, problem için en zarif ve basit çözümü imho olan – januszm

+1

Kabul ediyorum. Bu, mevcut işlevselliği kullanan en basit çözümdür. – CDub

0

ekleme başka bir olası çözüm kullanarak yordamlara: Ben, işe düşünüyorum olsun

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

proc = eval(string) 

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