The attached minimal gem contains a script that reads "Hello World!"
from its DATA section and then prints it.
The script works, but after installing (sudo gem install
datasection.gemspec), the wrapper in /usr/local/bin does not see the
DATA section:
$ datasection
/usr/local/lib/ruby/gems/1.9.1/gems/datasection-0.01/bin/datasection:2:in `<top
(required)>': uninitialized constant DATA (NameError)
from /usr/local/bin/datasection:19:in `load'
from /usr/local/bin/datasection:19:in `<main>'
In my actual script the DATA section is planned to contain a much larger
erb-template and it seems not very elegant to put those as strings in
the script.
DATA points to the contents after the __END__ directive of the executable
script that acts as an entry point (is not per file).
RubyGems wraps gem's executables with its own executables. Those wrappers
know where's the gem executable located, and also understand version
selection as an underscored argument. So, in a gem, the very gem's
executables are not the main files because of this indirection.
That's clear, but does that mean there's no workaround?
Can Ruby not be told that the DATA section is somewhere else?
···
On 2012-04-23 11:39, Xavier Noria wrote:
DATA points to the contents after the __END__ directive of the
executable script that acts as an entry point (is not per file).
RubyGems wraps gem's executables with its own executables. Those
wrappers know where's the gem executable located, and also understand
version selection as an underscored argument. So, in a gem, the very
gem's executables are not the main files because of this indirection.
That's clear, but does that mean there's no workaround?
Can Ruby not be told that the DATA section is somewhere else?
There's no workaround related to the DATA constant itself, it's defined
only for the main file.
You could of course switch to regular Ruby, for example throwing at the end
of the script:
BEGIN {
require 'stringio'
DATA = StringIO.new(<<EOS)
...
EOS
}
That'd work because the main file is not going to define DATA (RubyGems
does not generate __END__), so the constant is undefined. You could also
scan __FILE__ in a BEGIN block looking for __END__ by hand to fully emulate
the feature.
The BEGIN block is needed because in the original DATA feature you get the
constant defined in the top-level right away if __END__ is present.
Well just giving some ideas, the main point is that you need to do it in
Ruby.
···
On Mon, Apr 23, 2012 at 1:49 PM, Wybo Dekker <wybo@xs4all.nl> wrote:
On Mon, Apr 23, 2012 at 11:37 AM, Ender Ahmet Yurt <enderyurt@gmail.com> wrote:
no one knows how we can do it. (:
--
Darryl L. Pierce <mcpierce@gmail.com>
Visit the Infobahn Offramp: <http://mcpierce.multiply.com>
"Bury me next to my wife. Nothing too fancy..." - Ulysses S. Grant
That's great, thanks Peter, Ryan.
But it needs a correction, because the script is now also split on the
__END__ in the "data =..." line itself, so it needs a ^:
data = File.read(__FILE__).split(/^__END__/, 2).last
And Ryan's ,2 can be skipped if one wants more than one subsection in
the DATA section. Here's my test script, including the idea of using it
for erb templates:
name = 'Unknown'
OptionParser.new do |opt|
opt.on('-n','--name=STRING',String,
'set the name'
) do |v| name = v end
end.parse!
data1,data2 = File.read(__FILE__).
split(/^__END__/)[1..-1].
map { |x| ERB.new(x).result(binding) }
puts '',"data1: #{data1}", '',"data2: #{data2}"
__END__
Hello <%= name %>
This is data 1, two lines.
__END__
This is data 2,
3 lines,
including this one.
···
On 2012-04-23 22:57, Peter Zotov wrote:
Ryan Davis писал 23.04.2012 22:58:
On Apr 23, 2012, at 04:49 , Wybo Dekker wrote:
That's clear, but does that mean there's no workaround?
Can Ruby not be told that the DATA section is somewhere else?
This is my ((slightly?) horrible) workaround:
data = File.read(__FILE__).split(/__END__/).last
This is better:
data = File.read(__FILE__).split(/__END__/, 2).last
I you don't need the BEGIN block nor constants, I think you could just use some ordirary heredocs or some other conventional Ruby idiom.
···
Sent from my iPhone
On 24/04/2012, at 10:39, Wybo Dekker <wybo@xs4all.nl> wrote:
On 2012-04-23 22:57, Peter Zotov wrote:
Ryan Davis писал 23.04.2012 22:58:
On Apr 23, 2012, at 04:49 , Wybo Dekker wrote:
That's clear, but does that mean there's no workaround?
Can Ruby not be told that the DATA section is somewhere else?
This is my ((slightly?) horrible) workaround:
data = File.read(__FILE__).split(/__END__/).last
This is better:
data = File.read(__FILE__).split(/__END__/, 2).last
That's great, thanks Peter, Ryan.
But it needs a correction, because the script is now also split on the
__END__ in the "data =..." line itself, so it needs a ^:
data = File.read(__FILE__).split(/^__END__/, 2).last
And Ryan's ,2 can be skipped if one wants more than one subsection in
the DATA section. Here's my test script, including the idea of using it
for erb templates:
name = 'Unknown'
OptionParser.new do |opt|
opt.on('-n','--name=STRING',String,
'set the name'
) do |v| name = v end
end.parse!
data1,data2 = File.read(__FILE__).
split(/^__END__/)[1..-1].
map { |x| ERB.new(x).result(binding) }
puts '',"data1: #{data1}", '',"data2: #{data2}"
__END__
Hello <%= name %>
This is data 1, two lines.
__END__
This is data 2,
3 lines,
including this one.
I agree to Xavier, it's not such a big difference. Just do
# single quotes are important!
MY_DATA = <<'DAT'
doc is here
DAT
And if you place it at the end of the script you have pretty much the
same as with __END__ - plus, you can even define more documents that
way. You could also do
MY_DATA = %q{
doc is here
}
MY_DATA = %q[
doc is here
]
etc.
Kind regards
robert
···
On Tue, Apr 24, 2012 at 11:01 AM, Wybo Dekker <wybo@xs4all.nl> wrote:
On 2012-04-24 10:53, Xavier Noria wrote:
I you don't need the BEGIN block nor constants, I think you could just use some ordirary heredocs or some other conventional Ruby idiom.
sure, but as said in my initial mail, it's not very elegant to clog a
script with large blocks of erb templates...
Maybe I don't see the clue, but putting the doc at the end of the script
(and thus necessarily using it before its definition) results in:
uninitialized constant MY_DATA (NameError)
···
On 2012-04-24 11:08, Robert Klemme wrote:
# single quotes are important!
MY_DATA = <<'DAT'
doc is here
DAT
And if you place it at the end of the script you have pretty much the
same as with __END__ - plus, you can even define more documents that
way. You could also do
Putting it at the end does not necessarily mean you use it before the
definition especially if the file is a library file (i.e. no code gets
executed).
I cannot judge your case since your demo gem just contained demo
content. If you insist on having the data at the end, there are other
approaches as well:
rklemme@padrklemme2 /tmp/tmpenv.sh-8oDIBS
$ cat -n z.rb
1
2
3 def get
4 File.read(__FILE__)[%r{^=begi\s*#\s*DATA$\r?\n(.*)^=end\s*\z}m, 1]
5 end
6
7 =begin # DATA
8 This is
9 my
10
11 data
12 =end
Kind regards
rober
···
On Tue, Apr 24, 2012 at 2:59 PM, Wybo Dekker <wybo@xs4all.nl> wrote:
On 2012-04-24 11:08, Robert Klemme wrote:
# single quotes are important!
MY_DATA = <<'DAT'
doc is here
DAT
And if you place it at the end of the script you have pretty much the
same as with __END__ - plus, you can even define more documents that
way. You could also do
Maybe I don't see the clue, but putting the doc at the end of the script
(and thus necessarily using it before its definition) results in:
Did you receive my reply (I think it was the first one in the thread?) with
the BEGIN blocks? Do you know what is a BEGIN block?
···
On Tue, Apr 24, 2012 at 2:59 PM, Wybo Dekker <wybo@xs4all.nl> wrote:
On 2012-04-24 11:08, Robert Klemme wrote:
> # single quotes are important!
> MY_DATA = <<'DAT'
> doc is here
> DAT
>
> And if you place it at the end of the script you have pretty much the
> same as with __END__ - plus, you can even define more documents that
> way. You could also do
Maybe I don't see the clue, but putting the doc at the end of the script
(and thus necessarily using it before its definition) results in:
yes, but I didn't well understand it - now I see what you meant:
#!/usr/bin/env ruby
require 'optparse'
name = 'Unknown'
OptionParser.new do |opt|
opt.on('-n','--name=STRING',String,
'set the name'
) do |v| name = v end
end.parse!
puts '',"data1: #{DATA1.result(binding)}",
'',"data2: #{DATA2.result(binding)}"
# __TEMPLATES__
BEGIN {
require 'erb'
DATA1 = ERB.new(<<-'DAT')
Hello <%= name %>
This is data 1, two lines.
DAT
DATA2 = ERB.new(<<-'DAT')
This is data 2,
3 lines,
including this one.
DAT
}
···
On 2012-04-24 15:28, Xavier Noria wrote:
Did you receive my reply (I think it was the first one in the thread?)
with the BEGIN blocks? Do you know what is a BEGIN block?
Exactly! Given that __END__ is not per file, I think that solution is a
good compromise. It allows you to put this auxiliary stuff down the script,
and at the same time have it available in the main code.
One could invert the order and put the templates first, but I understand
your desire to put them down. That is, if __END__ was per file, we'd use it
for this case.