In Ruby, Can You Perform String Interpolation on Data Read from a File

In Ruby, can you perform string interpolation on data read from a file?

Instead of interpolating, you could use erb. This blog gives simple example of ERB usage,

require 'erb'
name = "Rasmus"
template_string = "My name is <%= name %>"
template = ERB.new template_string
puts template.result # prints "My name is Rasmus"

Kernel#eval could be used, too. But most of the time you want to use a simple template system like erb.

Is it possible to define a specific part of a string in an external file as a variable?

If I understand your question correctly, you have some external data file in JSON format, whose structure has certain fields as XPath strings on which you would like to perform Ruby string interpolation.

The short answer is that yes, you can do this directly using, say Kernel#eval. There are also other options such as using erb. A solution using the simple "eval" route might look like this:

xpaths = JSON.load(File.read('my-xpaths.json'))
(1..5).each do |i|
xpath = eval(xpaths['location']['elements'].to_json)
# => "//ul[@id='locations']/li[1]/a"
end

Of course, using "eval" is fraught with peril since you are essentially executing code from another source, so there are many precautions you must take to ensure safety. A better approach might involve doing a simple regular expression replacement so that you can constrain the interpolation on the XPath item:

xpaths['location']['elements'] # => "//ul[@id='locations']/li[__INDEX__]/a"
xpath = xpaths['location']['elements'].gsub(/__INDEX__/, i.to_s)
# => "//ul[@id='locations']/li[1]/a"

See also this related question: In Ruby, can you perform string interpolation on data read from a file?

How to interpolate ruby inside of an interpolated bit of ruby in ERB

I think the fact that I wasn't clear made it hard to answer this question.
What I'm doing is transforming user-inputted text (using a method in the model, called by the controller) to replace certain keywords with erb tags that call the best_in_place plugin. In my view, when presenting this content to another user, I wanted to call this content, which is saved as an attribute in the database, in such a way that it would render correctly for the other user to have the best_in_place functionality active.

Here's what I ended up doing. It is working, but if you have better ideas, please let me know.

In the announcements#create view, the user creates an announcement with certain pre-defined blocks of bracketed text as well as free-input text. For example, they might write "[train] is leaving from [platform] in [time] minutes."

When they hit save, the controller's create action calls the construct_message method from the model. It looks like this:

def construct_message(msg)
msg.gsub! '[train]', '<%= best_in_place @announcement, :train_id, :as => :select, collection: Train::list_trains, place_holder: "Click here to set train." %>' #note: list_trains and list_platforms are methods on the model, not really important...
msg.gsub! '[platform]', '<%= best_in_place @announcement, :platform_id, :as => select, collection: Platform::list_platforms, placeholder: "Click here to set platform." %>'
msg.gsub! '[time]', '<%= best_in_place @announcement, :number_of_minutes, placeholder: "Click here to set." %>'
end

Then, when I want to show that attribute in my view, I'm using render :inline, like this.

on announcements/:id

<p id="notice"><%= notice %></p>

<p>
<strong>Content:</strong>
<% announcement = @announcement %>
<%= render :inline => announcement.content, locals: { :announcement => announcement } %>
</p>

This allows the erb call that I wrote into the attribute to be functional.
Also note that I'm choosing to use a local rather than instance variable here; this is because in announcements#index, I also render this text and the table there uses local variables.

String interpolation in form inputs


= semantic_form_for element, url: form_url, method: form_method, remote: true do |f|
// there will be some form should return once
- %w(webm mp4 ogv).each do |ext|
.video-item-uploader
= f.input :"#{ext}", hint: [ f.object.send("#{ext}?")? ? "#{I18n.t('uploaded')}" : '' ].join.html_safe
= f.input :"#{ext + '_cache'}", as: :hidden

= f.input :_destroy, as: :boolean, label: "#{I18n.t('do_delete')}"

try this

Rails String Interpolation in a string from a database

If you want

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

in your database, use single quotes or escape the # with a backslash to keep Ruby from interpolating the #{} stuff right away:

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

Then, later when you want to do the interpolation you could, if you were daring or trusted yourself, use eval:

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

Note that you'll have to turn s into a double quoted string in order for the eval to work. This will work but it isn't the nicest approach and leaves you open to all sorts of strange and confusing errors; it should be okay as long as you (or other trusted people) are writing the strings.

I think you'd be better off with a simple micro-templating system, even something as simple as this:

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

You could use whatever delimiters you wanted of course, I went with {{...}} because I've been using Mustache.js and Handlebars.js lately. This naive implementation has issues (no in-template formatting options, no delimiter escaping, ...) but it might be enough. If your templates get more complicated then maybe String#% or ERB might work better.

String interpolation in HTML attributes in an ERB file


data-text = "I won #{@credits} by playing..."

You can apply the same principle for the other string, like so:

data-url = "#{request.scheme}//#{request.port}" 

can you use the ruby percent notation for strings with interpolation?

Try %Q instead of %q. For instance:

catchphrase = 'wubba lubba dub dub'
%Q[My new catchphrase is "#{catchphrase}"] #=> "My new catchphrase is \"wubba lubba dub dub\""

How to use a variable for a file path? Ruby

You can use variable inside string, following way:

array.to_csv("#{location}\FileName.csv")

Interpolating an XML string containing double quotes and colons in Ruby

As suggested by Jörg, you'll have much better experience if you use one of the templating languages. I suggested ERB, because it's built-in.

xs = '<ns1: xmlns:ns1="http://example.com" attr="<%= Time.now %>">'

require 'erb'
ERB.new(xs).result(binding)
# => "<ns1: xmlns:ns1=\"http://example.com\" attr=\"2017-06-23 09:11:56 +0300\">"


Related Topics



Leave a reply



Submit