Reading a file in Rails Template
I'm making a Rails template file as introduced below:
- http://asciicasts.com/episodes/148-app-templates-in-rails-2-3
I have a big file I want to make, so instead of doing:
file "bigfile.txt", <<-EOF
content of the file...
EOF
I want to read the content from another file. What I have now is:
file "public/stylesheets/sass/960.sass", File.read(File.expand_path(File.join(File.dirname(__FILE__), "960.sass")))
The file is located in the same dire开发者_如何转开发ctory as the rails template file. The problem is: when I try to make a rails app with the template (i.e., rails new_app -m rails_template/rails_template.rb
, I get the following error:
The template [rails_template/rails_template.rb] could not be loaded. Error: (eval):129:in `read': No such file or directory - /Users/myusername/Desktop/new_app/960.sass
This is all because __SELF__
is not working the way I expected. I expect __SELF__
to be the template file itself, but in reality, __SELF__
is poiting to the root of the app or somewhere else.
Is there a way to load file in a rails template?
There is no problem reading a file from within a template. If you were to hard code the path to the source copy of 960.sass then it would work fine.
As you suspect the problem lies with the use of __FILE__
. The reason is that if you look in rails-2.3.4\lib\rails_generator\generators\applications\app\template_runner.rb you will see that load_template
loads the template into a string and then executes it using instance_eval
:
def load_template(template)
begin
code = open(template).read
in_root { self.instance_eval(code) }
rescue LoadError, Errno::ENOENT => e
raise "The template [#{template}] could not be loaded. Error: #{e}"
end
end
Hence when your code executes the context is an eval block and __FILE__
won't point to your file.
The good news is that the template
parameter passed to load_template
(containing the path to your template) is a local variable at the point when instance_eval
is called and so is available from the code inside your template. If instead you just do:
File.dirname(template)
then it should work. Be aware though that you are then tying your code to the current implementation of load_template
, which could change in the future.
精彩评论