2011-07-21 28 views
11

Vì vậy, đây là vấn đề của tôi.Nội suy chuỗi đường ray trong một chuỗi từ cơ sở dữ liệu

Tôi muốn truy xuất một chuỗi được lưu trữ trong một mô hình và khi thời gian chạy thay đổi một phần của nó bằng cách sử dụng một biến từ ứng dụng đường ray. Dưới đây là ví dụ:

Tôi có một Mô hình thư mà tôi sử dụng để lưu trữ một số thư duy nhất. người dùng nên khác nhau có cùng một thông điệp, nhưng tôi muốn để có thể hiển thị tên của họ ở giữa tin nhắn, ví dụ:

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

tôi đã cố gắng để lưu trữ chính xác điều đó trong cơ sở dữ liệu nhưng nó được thoát trước khi hiển thị trong khung nhìn hoặc được nội suy khi lưu trữ trong cơ sở dữ liệu, thông qua bảng điều khiển đường ray.

Xin cảm ơn trước.

Trả lời

9

Nếu bạn muốn

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

trong cơ sở dữ liệu của bạn, sử dụng dấu ngoặc đơn hoặc thoát khỏi # với một dấu gạch chéo để giữ Ruby từ nội suy những thứ #{} ngay lập tức:

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

Sau đó, sau khi bạn muốn làm nội suy bạn có thể, nếu bạn táo bạo hoặc tin tưởng bản thân, hãy sử dụng eval:

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

Lưu ý rằng bạn sẽ phải chuyển s thành chuỗi được trích dẫn kép để eval hoạt động. Điều này sẽ làm việc nhưng nó không phải là cách tiếp cận đẹp nhất và lá bạn mở cho tất cả các loại lỗi lạ và khó hiểu nhưng nó sẽ không sao miễn là bạn (hoặc những người đáng tin cậy khác) đang viết các chuỗi; Tôi nghĩ rằng bạn muốn được tốt hơn với một hệ thống vi khuôn mẫu đơn giản, ngay cả một cái gì đó đơn giản như này:

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

Bạn có thể sử dụng bất cứ điều gì bạn muốn delimiters tất nhiên, tôi đã đi với {{...}} vì tôi đã sử dụng Mustache.js và Handlebars.js gần đây. Việc triển khai ngây thơ này có vấn đề (không có tùy chọn định dạng trong mẫu, không có dấu phân cách thoát, ...) nhưng có thể là đủ; nếu các mẫu của bạn trở nên phức tạp hơn thì bạn có thể muốn lưu trữ các bit của ERB trong cơ sở dữ liệu và sử dụng bộ xử lý ERB trong thỏa thuận thư viện chuẩn với nó.

+0

Cảm ơn, đã làm việc ... Tôi đã lưu trữ chuỗi trích dẫn đơn lẻ. Tôi đã bỏ lỡ cách nội suy sau khi lấy nó từ cơ sở dữ liệu. Tôi biết về rủi ro bảo mật xung quanh việc sử dụng điều này, nhưng người dùng không thể thay đổi chuỗi này trực tiếp. –

+0

Tôi sẽ thêm rằng nếu chuỗi của bạn chứa HTML sử dụng phương thức 'raw' (http://apidock.com/rails/ActionView/Helpers/OutputSafetyHelper/raw) và phương thức' html_safe'. – dennismonsewicz

0

một cách tôi có thể nghĩ để làm điều này là phải có mẫu được lưu trữ ví dụ:

"hi tên"

sau đó có một chức năng trong các mô hình mà chỉ thay thế các thẻ mẫu (tên) với truyền lập luận. Nó cũng có thể là Người dùng đã đăng nhập.

Vì chức năng mới này sẽ là một phần của mô hình, bạn có thể sử dụng nó như một trường khác của mô hình từ bất kỳ đâu trong đường ray, bao gồm tệp html.erb.

Hy vọng điều đó sẽ hữu ích, hãy cho tôi biết nếu bạn cần thêm mô tả.

+0

tôi nhận được nó, tôi nghĩ rằng nó sẽ làm việc, vấn đề tôi thấy trong này là tôi sẽ phải xác định tất cả các thẻ có thể, tôi có thể sử dụng và bản đồ mỗi một đến các biến/hàm tương ứng bên trong ứng dụng. Chỉ cần nghĩ rằng sẽ có một cách đơn giản hơn để làm điều này, giống như nội suy cho một chuỗi bình thường. –

+0

tôi nghĩ rằng cách tiếp cận của bạn cũng nên hoạt động. Bạn có thể tránh chuỗi mà bạn đang tạo ra được nội suy trước khi được lưu trữ trong cơ sở dữ liệu bằng cách tạo chuỗi bằng cách sử dụng dấu nháy đơn thay vì dấu ngoặc kép. Tôi không chắc chắn lý do tại sao nó được thoát ra trước khi đến xem. – Shaunak

+0

Tôi đã lưu trữ phiên bản được trích dẫn duy nhất, nhưng nó được chuyển thành chuỗi được trích dẫn kép đã thoát trước khi lưu trong cơ sở dữ liệu. –

34

Tôi không thấy lý do để xác định chức năng trình trợ giúp chuỗi tùy chỉnh. Ruby cung cấp very nice formatting approaches, ví dụ::

"Hello %s" % ['world'] 

hoặc

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

Cả hai ví dụ trở lại "Hello world".

+5

Đây là giải pháp đơn giản và thanh lịch nhất cho vấn đề – januszm

+1

Tôi đồng ý. Đây là giải pháp đơn giản nhất sử dụng chức năng hiện có. – CDub

0

Thêm một giải pháp có thể sử dụng Procs:

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

proc = eval(string) 

proc.call(User.find(1)) #=> "Hello Bob" 
Các vấn đề liên quan