require File.expand_path(File.dirname(__FILE__ ...

299 views
Skip to first unread message

Ed Howland

unread,
Oct 29, 2009, 1:09:27 PM10/29/09
to stl...@googlegroups.com
Hey guys. How's the weather there? Cold here.

I was wondering something. I see this all the time at the top of
files, or some variation of it that uses File.join. Another approach
is to augment the load path, or $:

Since this is such a common idiom, why hasn't it been converted into a
gem? What I think is the reason, is because in order to do one
require, you'd have to do 2 other ones: rubygems, and the gem that had
the File.expand_path. Also, the __FILE__ would have to be passed in,
since it would be different for the gem .rb file.

But, 1.9 has gems built in. So for that, it would make sense if you
had to require a lot of files. Something like:

require "relative_require"
require_relative __FILE__, "..", "lib". "methods1"
...
require_relative __FILE__, "..", "lib". "methods3"
require_relative __FILE__, "../lib/methods4"

-- or --
require "relative_require
augment_path __FILE__, "..", "lib"
require "methods1"
..
require "methods4"

Also, do they use the File.join idiom to make it portable to Windows?

Am I missing something?

Thanks
Ed

--
Ed Howland
http://greenprogrammer.blogspot.com
http://twitter.com/ed_howland

Ed Howland

unread,
Oct 29, 2009, 1:46:08 PM10/29/09
to stl...@googlegroups.com
A little research netted the following:
http://extensions.rubyforge.org/rdoc/classes/Kernel.html

Seems, this discussion has been going on for a while. Matz has
consistently turned it down for core, but it seems to be in my 1.9.1
compiled for Mac, anyway, though the Internets say it is scheduled for
1.9.2.

My guess is it isn't portable, at least not to the 1.8.x crowd (LUsers :)

HaHa.

I also don't like that it takes a single argument, instead of *paths.
Again I wonder about the Windows users. Also, I do like that it
doesn't need __FILE__, since it extends module Kernel and uses the
caller[0] for that.

Ed

Craig Buchek

unread,
Oct 29, 2009, 1:55:50 PM10/29/09
to Saint Louis Ruby Users Group
Yes, the File.expand_path/File.join idiom is used for systems that
don't follow the POSIX (UNIX) conventions for using forward slashes
(/) as path separator.

> How's the weather there? Cold here.

Cold and rainy. We've had more rain this October than any on record.

> I was wondering something. I see this all the time at the top of
> files, or some variation of it that uses File.join. Another approach
> is to augment the load path, or $:

Yeah, it would be nice to have something more standard, instead of 3
or 4 different idioms.

Craig

Jeff Barczewski

unread,
Nov 6, 2009, 5:37:04 PM11/6/09
to stl...@googlegroups.com
I agree Ed, it is crazy to be still using File.dirname(__FILE__) which reminds me of C macros to do something that is extremely common.

If nothing else, I'd like to see __DIR__ to at least eliminate the above.

It is hard to believe how sometimes people get so entrenched against an idea rather than coming up with a real solution.

Ed Howland

unread,
Nov 7, 2009, 1:24:02 PM11/7/09
to stl...@googlegroups.com
I agree Jeff. Currently, I am using require_relative() which came in
the recent Ruby 1.9.1. It seems to be canon now, for instance, the
Ruby backports gem has it.

But if you are writing a gem or an app and you want to make it 1.8
compatible, then you'd have to resort to requiring backports, (an
unneeded dependency), or use the File.expand_path(...) method. I hope
that 1.8.8 addresses this. [1]

Also, I wish that along with require_relative(), they could provide a
similar facility for $LOAD_PATH. Such as add_load_path("../lib/"). If
you distribute your app with an internal local gems directory (ala
Rails - vendor/gems) this could be useful for third party gems that
require each other. There is an environment variable GEM_PATH and
GEM_HOME that can be manipulated. Although some consider that rude.
But, since rubygems is native in 1.9+, there ought to be a way to set
the load path easily for them.

Then there is also the ~/.gem directory which recently caused me some
issues. One thing that is useful in that regard is deploying Rails
apps on a hosting site that doesn't let you install gems in the
standard gem path path (I am mostly referring to gem supplied
executables like cucumber, spec).

Also, I saw a demo at the GRRUG Tuesday of a Sinatra add-on that
included a require remote facility. If the gem was not installed on
the local system, it fetched it first, installed it (~/.gem?) and then
required it. Sweet (for some scenarios). I'll find out more and share
it.

There is also "http-require" which really only works with pure Ruby
gems (no native compiles), I think.


Ed

[1] It's times like these when I miss the preprocessor macro facility in C.
If you do a "sudo gem install mygem", then it already checks the
current version of ruby to determine the gem path.
(/usr/local/lib/ruby/gems/1.9.1/gems ...) I'd like it to supply a
preprocessor macro that you could do in your gem file like this:

#!if RUBY_VERSION < 1.9
require "rubygems"
#!endif
require "some_gem"

Then the actual gem file would get installed for the right Ruby version.

Craig Buchek

unread,
Nov 8, 2009, 3:55:43 PM11/8/09
to Saint Louis Ruby Users Group
> I hope that 1.8.8 addresses this.

Is there a Ruby 1.8.8 pending? Any info on it?

> #!if RUBY_VERSION < 1.9
> require "rubygems"
> #!endif
> require "some_gem"

Ed, you do realize that you can do that in Ruby, right?


Ed Howland

unread,
Nov 9, 2009, 2:25:49 PM11/9/09
to stl...@googlegroups.com
Craig,

I don;t know if there is one. I know of a lot of bugs fixed in 1.6.7.
Maybe it will just be a patch level release.

O know you can do it in Ruby, but I was hoping to be able to provide
the gem installer with a hint about which version dir to drop the
library file into once it has been preprocessed. There is talk about
providing multiple architecture gems, and I hope that translates into
multiple ruby environments as well.

On that note, Robert Citek and I came up with a nice way to
switch between ruby 1.6 and 1.9.1 on Ubuntu Karmic. If you install
both 1.8 and 1.91 via apt-get, you get the 1.9.1 versions with 1.9,1
appended to each executable (/usr/bin/ruby1.9.1, /usr/bin/irb1.9.1
etc.).

Then set up ~/bin/ making sure it is first in you path. Create 2
scripts to ln the desired executables to ~/bin/ruby, ~/bin/irb
whatever. This is only viable for personal development. Not for
system-wide deployment.

BTW, Cucumber and RSpec install and work just fine under both if you
install twice via sudo gem install using both versions of Ruby (need
to double check that, tho). Then you should be able to cross-check
with your regression tests.

Upcoming blog post about this. Stay tuned.


Cheers
Ed,

Too god a day to be on the cimputer. See ya later!

Ed

Gordon Thiesfeld

unread,
Nov 9, 2009, 3:56:41 PM11/9/09
to stl...@googlegroups.com
On Mon, Nov 9, 2009 at 1:25 PM, Ed Howland <ed.ho...@gmail.com> wrote:

> On that note, Robert Citek and I came up with a nice way to
> switch between ruby 1.6 and 1.9.1 on Ubuntu Karmic. If you install
> both 1.8 and 1.91 via apt-get, you get the 1.9.1 versions with 1.9,1
> appended to each executable (/usr/bin/ruby1.9.1, /usr/bin/irb1.9.1
> etc.).
>

Have you tried RVM [1]? I'm using it on Ubuntu Karmic. I also have a
project called pik[2], which does something similar for windows users.

[1] http://rvm.beginrescueend.com/
[2] http://github.com/vertiginous/pik

Gordon

Jeff Barczewski

unread,
Nov 20, 2009, 5:13:34 PM11/20/09
to stl...@googlegroups.com
It looks like Matz ok's adding __DIR__ or __dir__ in this thread, he just wanted someone to submit a patch.

http://redmine.ruby-lang.org/issues/show/1961


I don't see that anyone did at least on this thread.

The last post actually points to some github code that implemented it.

http://github.com/manveru/ramaze/blob/master/lib/ramaze/snippets/object/__dir__.rb

Maybe someone needs to simply create a patch and submit it to this thread??

Jeff

Ed Howland

unread,
Nov 21, 2009, 1:28:05 PM11/21/09
to stl...@googlegroups.com
I like the Ramaze implementation of __DIR__(*args)

But there seems to be a difference between ruby versions wrt to
caller. On 1.9.1, I get something like this for caller[0]:
"/Users/edh/ruby/caller.rb:7:in `b'"

The path is fully expanded.

in 1.8.7:
rvm 1.8.7
irb

irb(main):006:0> caller[0][0][/^(.*):\d+:/,1]
=> "./caller.rb" # (within a method)

The path seems to be relative, depending on how the file was called.
But File.expand_path() works with this.


Note the extra colon, e.g. ":7:" which breaks Ramaze's regex
caller[0][/^(.*):/, 1] => "/Users/edh/ruby/caller.rb:7"

Note we get the line number too. I changed it to:
caller[0][/^(.*):\d+:/, 1]
=> "/Users/edh/ruby/caller.rb"

And it works:
(Extract the module Object from Ramaze's file and rename it to class Object).

irb(main):011:0* load "./dir.rb"
=> true
irb(main):006:0> Dir.chdir(__DIR__("run-calc", "features", "support")) do
irb(main):007:1* puts Dir.glob("*.rb")
irb(main):008:1> end
env.rb
paths.rb

Can anyone explain how :
[/^(.*):\d+:/,1]

works?

Overall, I hope Matz implements something like this feature.

Thanks,
Ed
> --
>
> You received this message because you are subscribed to the Google Groups
> "Saint Louis Ruby Users Group" group.
> To post to this group, send email to stl...@googlegroups.com.
> To unsubscribe from this group, send email to
> stlruby+u...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/stlruby?hl=.

Craig Buchek

unread,
Nov 23, 2009, 11:35:25 AM11/23/09
to Saint Louis Ruby Users Group
> I like the Ramaze implementation of __DIR__(*args)

I don't much care for allowing __DIR__ to take args as a method.
__FILE__ is just a constant String, and I think __DIR__ should mirror
its implementation as much as possible.

> Can anyone explain how :
> [/^(.*):\d+:/,1]
> works?

The regex matches up until it reaches a colon, some digits (\d+), and
another colon. Then it stores what got matched within the parentheses.
Since it's the first open paren, it stores it into match variable 1.
The [regex, match_num] idiom in Ruby is pretty cool -- it makes it
easy to grab a piece of a string using a matching regex. I wish I
could find some online documentation on it (online docs for __FILE__
seem to be hard to find too). I'd bet it's in the better Ruby books
though.

BTW, I just found this alternative idiom for the equivalent to
__DIR__:

File.expand_path('..', __FILE__)

Nice!

Ed Howland

unread,
Nov 23, 2009, 2:35:24 PM11/23/09
to stl...@googlegroups.com
Craig,

There is some discussion on this in the Ruby dev list (where Matz
hangs out). I'm not sure where he is going to end up, #Kernel.__dir__,
__dir__(*paths), __DIR__ or __DIR__(*paths). I think the consensus
might be for __DIR__ as a constant as you say. You can write your own
function that does a similar thing, assuming __DIR__ exists:

def relative_path(*paths)
File.join(__DIR__, *paths)
end

As far as "string"[/.../,1], goes, I got the regex, but this is a cool
idiom, nonetheless.

rb(main):010:0> "word word1 word2"[/\w+ (\w+) (\w+)/,2]
=> "word2"


The docs are sort of buried in the String class doc(#5 below)::
from [1]:
str[fixnum] => fixnum or nil
str[fixnum, fixnum] => new_str or nil
str[range] => new_str or nil
str[regexp] => new_str or nil
str[regexp, fixnum] => new_str or nil
str[other_str] => new_str or nil
str.slice(fixnum) => fixnum or nil
str.slice(fixnum, fixnum) => new_str or nil
str.slice(range) => new_str or nil
str.slice(regexp) => new_str or nil
str.slice(regexp, fixnum) => new_str or nil
str.slice(other_str) => new_str or nil

"If a Regexp is supplied, the matching portion of str is returned. If
a numeric parameter follows the regular expression, that component of
the MatchData is returned instead."

Regards,
Ed

[1] class String#str[] http://ruby-doc.org/core/classes/String.html#M000771

Craig Buchek

unread,
Nov 23, 2009, 4:04:50 PM11/23/09
to Saint Louis Ruby Users Group
Duh. I should have realized that I should look in the String class for
the [] method. Even crazier is the assignment form:

str[regexp, fixnum] = new_str

I had a hard time finding documentation for __FILE__. It turns out
that it's a Ruby keyword, and a pseudo-variable, like true/false/nil/
self. David Black added documentation for these in 1.9:
http://ruby-doc.org/docs/keywords/1.9/.

Craig

Jeff Barczewski

unread,
Dec 11, 2009, 5:51:31 PM12/11/09
to Saint Louis Ruby Users Group
I asked Matz about this __dir__ request at the Q&A with Matz session
of RubyConf 2009 and he said they would plan to put it into 1.9.2.

Looks like it got assigned to Matz the week after the RubyConf
conference. Yay! :-)

http://redmine.ruby-lang.org/issues/show/1961

Jeff

Mario Aquino

unread,
Dec 11, 2009, 9:26:09 PM12/11/09
to stl...@googlegroups.com
Oh man!  Cool as hell.

--

You received this message because you are subscribed to the Google Groups "Saint Louis Ruby Users Group" group.
To post to this group, send email to stl...@googlegroups.com.
To unsubscribe from this group, send email to stlruby+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/stlruby?hl=en.



Reply all
Reply to author
Forward
0 new messages