Feature #11997
closedA method to read a file with interpolations
Description
I request a single method that reads a file while interpreting interpolated Ruby code in it (in the current context). For example, suppose I have a file foo.txt.
foo.txt
#{char * 20}
Hello, my name is #{name}.
#{char * 20}
I am not sure about what method name the proposed feature should have, and on which class it should be defined, but let's temporarily call it File.eval. Then I would like to do:
char = "*"
name = "John Doe"
File.eval("foo.txt") # => "********************\nHello, my name is John Doe.\n********************\n"
The use case that I have in mind is to easily create template engines/preprocessors, or do an equivalent of what such software do on the fly within a script. There are tools like erb, SCSS, haml, etc., but those force a particular syntax, and they are full fledged software with their own parsing capability, which means it takes an extra time to parse, and the sortware may have their own bugs. I often feel that I do not want to adopt any of the syntax forced in those limited choice of template/preprocessing software, but do it in a freer way.
Using what we have currently, I can do it with:
eval('"' + File.read("foo.txt") + '"')
but that looks cumbersome, and wish if Ruby had a C-level built-in capability for doing that. I believe that would encourage wide range of Ruby users to more freely create their own templating system.
Updated by nobu (Nobuyoshi Nakada) almost 10 years ago
- Status changed from Open to Feedback
Why not erb?
Updated by sawa (Tsuyoshi Sawada) almost 10 years ago
Why not erb?
Erb syntax is too much noise to me. It is centered toward html (it resembles html tagging), which is notorious for being a human-unfriendly notation. And it does not look that good when used for things other than an html file. I never felt comfortable with it. Ruby's interpolation syntax #{} is simple, and does not require learning additional things, once you know Ruby.
Updated by justcolin (Colin Fulton) over 9 years ago
I agree that ERB is ugly for a lot of cases, but—since there is a one liner to write this in Ruby—I don't think it needs to be added to the core language.
EDIT: After thinking about this for a while longer, I think this would be a nice thing to add. It should be very easy to implement in core and would provide a templating syntax that looks a lot more Ruby-ish than ERB.
Updated by justcolin (Colin Fulton) over 9 years ago
As far as implementation, File.eval doesn't feel right since you may want any IO object—or any object with #read—to be eval-able. Also giving File the ability to do eval feels like it violates the single responsibility principle a bit too much. Instead maybe #eval or #instance_eval/#instance_exec/#class_eval/etc. should accept instances of IO or IO-like objects as an argument. Calls would then look something like:
eval File.new('../pugs.txt')
Updated by shyouhei (Shyouhei Urabe) over 9 years ago
This is difficult to implement in-core than it sounds. String interpolation is tightly built into our parser; hard to extirpate. A built-in for this feature would accordingly result in the same eval + File.read maneuver, to just translate into C.
Updated by mame (Yusuke Endoh) over 9 years ago
-1. I don't think that this is suitable as a core feature. We should leave such a thing to a library like erb.