Refining the use of file joins or file expand_path

A

Alpha Blue

Both bits of code process the same result which is finding .rb file
extensions within a specified relative path.

The question I have (because I have written used both) is which would
"you" use and why keeping the following in mind...

Ruby 1.9.x
Cross - OS usability (windows/linux/mac/etc.)

Dir[File.join(File.dirname(__FILE__),"..","ui","*.rb")].each {|rb_files|
load rb_files}

Dir[File.expand_path('../../ui/*.rb', __FILE__)].each {|rb_files| load
rb_files}

Thanks.
 
I

Iñaki Baz Castillo

El S=C3=A1bado, 30 de Enero de 2010, Alpha Blue escribi=C3=B3:
Both bits of code process the same result which is finding .rb file
extensions within a specified relative path.
=20
The question I have (because I have written used both) is which would
"you" use and why keeping the following in mind...
=20
Ruby 1.9.x
Cross - OS usability (windows/linux/mac/etc.)
=20
Dir[File.join(File.dirname(__FILE__),"..","ui","*.rb")].each {|rb_files|
load rb_files}
=20
Dir[File.expand_path('../../ui/*.rb', __FILE__)].each {|rb_files| load
rb_files}

I prefer the first one.


=2D-=20
I=C3=B1aki Baz Castillo <[email protected]>
 
R

Ryan Davis

Both bits of code process the same result which is finding .rb file
extensions within a specified relative path.
=20
The question I have (because I have written used both) is which would
"you" use and why keeping the following in mind..

Neither. I write sane code with sane requires and sane load paths. I =
also NEVER glob my requires.
Ruby 1.9.x
Cross - OS usability (windows/linux/mac/etc.)
=20
Dir[File.join(File.dirname(__FILE__),"..","ui","*.rb")].each = {|rb_files|
load rb_files}
=20
Dir[File.expand_path('../../ui/*.rb', __FILE__)].each {|rb_files| load
rb_files}

My version:
require "x/ui/blah1"
require "x/ui/blah2"
assuming:

lib/x/ui/blah[12].rb

It is 100% easier to read, maintain, and understand. There's no magic, =
and nothing to debug because you don't pull in stuff you didn't expect.
 
A

Alpha Blue

Ryan said:
My version:
require "x/ui/blah1"
require "x/ui/blah2"
assuming:

lib/x/ui/blah[12].rb

It is 100% easier to read, maintain, and understand. There's no magic,
and nothing to debug because you don't pull in stuff you didn't expect.

That doesn't work for all operating systems.
 
P

pharrington

Ryan said:
My version:
require "x/ui/blah1"
require "x/ui/blah2"
assuming:
lib/x/ui/blah[12].rb

It is 100% easier to read, maintain, and understand. There's no magic,
and nothing to debug because you don't pull in stuff you didn't expect.

That doesn't work for all operating systems.

It'll at least work on Windows, Linux, and OSX. For what OSs will
forward slashes in the path not work?
 
P

pharrington

Ryan said:
My version:
require "x/ui/blah1"
require "x/ui/blah2"
assuming:
lib/x/ui/blah[12].rb
It is 100% easier to read, maintain, and understand. There's no magic,
and nothing to debug because you don't pull in stuff you didn't expect.
That doesn't work for all operating systems.

It'll at least work on Windows, Linux, and OSX. For what OSs will
forward slashes in the path not work?

Not that that's even really the point, though :\
 
A

Alpha Blue

pharrington said:
It'll at least work on Windows, Linux, and OSX. For what OSs will
forward slashes in the path not work?

Tops-20
OpenVMS
Classic MAC OS
RISC OS
Symbian OS
Stratus VOS
etc.

Also, if you accidentally nest a require, say for example:

--root\
-- app.rb
----\lib
---- main.rb
---- modules.rb

.. note that modules.rb and main.rb are within the same directory
(main).

If your app.rb has require 'lib/main'
.. and
If your main.rb has require 'modules'

...


(in E:/Gui-Development/GuiTemplate)
ruby app.rb
E:/Gui-Development/GuiTemplate/lib/main.rb:2:in `require': no such file
to load
-- modules (LoadError)
from E:/Gui-Development/GuiTemplate/lib/main.rb:2:in `<top
(required)>'
from app.rb:8:in `require'
from app.rb:8:in `<main>'
rake aborted!
Command failed with status (1): [ruby app.rb...]

(See full trace by running task with --trace)

.. now take the same require 'modules' out and place:

require File.join(File.dirname(__FILE__),"modules")

.. and no errors.

main.rb and modules.rb are relative to each other. But, if you start an
application from a different directory, the require has to have a
defined path.
 
R

Ryan Davis

Ryan said:
My version:
=20
require "x/ui/blah1"
require "x/ui/blah2" =20
assuming:
=20
lib/x/ui/blah[12].rb
=20
It is 100% easier to read, maintain, and understand. There's no = magic,=20
and nothing to debug because you don't pull in stuff you didn't =
expect.
=20
That doesn't work for all operating systems.

As pointed out by others... yes... yes it does. For ruby's definition of =
"all" that is.
 
R

Ryan Davis

=20
Tops-20
OpenVMS
Classic MAC OS
RISC OS
Symbian OS
Stratus VOS
etc.

uh... wuh?
Also, if you accidentally nest a require, say for example:
=20
--root\
-- app.rb
----\lib
---- main.rb
---- modules.rb
=20
.. note that modules.rb and main.rb are within the same directory=20
(main).
=20
If your app.rb has require 'lib/main'
.. and
If your main.rb has require 'modules'

OK. Stop. Let's just stop right there. you obviously overlooked the part =
where I said SANE.
 
A

Alpha Blue

Ryan said:
uh... wuh?

I was only providing a list in answer to Pharrington. Call it Saturday
night satire. I think I provided most, if not all operating systems
that won't accept a forward slash via path.. but I could have missed one
or two. But, no need to respond to this bit. :)
OK. Stop. Let's just stop right there. you obviously overlooked the part
where I said SANE.

Everyone makes mistakes, especially programmers that are still in
transition. I've accidentally done the exact thing I described and it
happens. I'm sure you did the same thing or something similar as you
started programming with ruby. My issue is that I've worked in several
other languages, so I try to learn the best practices, which is why I
posted this question here. Right now, for me, it seemed best to make
sure I used a failsafe relative path in case my code turned out to not
be sane.

I'm a very easy going guy and I love to learn. I am working with WxRuby
right now and at the moment, even though I like the feel of the library,
I find the way it interacts with classes cumbersome. I'm trying to
design my own project template so that I can use it for base projects
going forward.

You have me pegged wrong. I see what you are saying, but apparently
we're speaking from within two different paradigms.
 
A

Alpha Blue

Just to clarify what I mean about paradigms,

I mean you are coming from a 10-year or so run with ruby so that's one
world, and I'm only coming from a 1-year stint with ruby. So, it's two
completely different worlds.

Some of what you are saying probably seems very simple to you, and at
first glance, it appears simplified to me. Then my mind looks at it and
coming from other languages I begin to think, it can't just be that
simple...

I hate feeling that way, but it happens sometimes...

As a follow-up to your earlier post,

If you were designing a GUI template, how would you structure your work
space so that it allowed for sane requires and includes?

That answer would help me out a great deal as I tend to organize things
better with a diagram or schematic...

Thanks.
 
M

Marnen Laibow-Koser

Alpha said:
Just to clarify what I mean about paradigms,

I mean you are coming from a 10-year or so run with ruby so that's one
world, and I'm only coming from a 1-year stint with ruby. So, it's two
completely different worlds.

Then learn the correct paradigm.

Best,
 
A

Alpha Blue

Marnen said:
Then learn the correct paradigm.

The comment was really unnecessary Marnen, especially since I was only
responding to one person. You don't learn a paradigm; you are part of a
paradigm. I was trying to state that learning takes time and when
someone has 10 years under their belt, of course things are simpler to
them.

When moving to another language, the first year is really spent breaking
old mindsets and philosophies. Ruby is a very good OOL and it's must
easier to use than other languages. I'm thankful for that.

Ryan and Pharrington provided input into the topic and I thank them.
You did not.
 
M

Marnen Laibow-Koser

Alpha said:
The comment was really unnecessary Marnen, especially since I was only
responding to one person. You don't learn a paradigm; you are part of a
paradigm.

Wrong, at least the way I use that word.
I was trying to state that learning takes time and when
someone has 10 years under their belt, of course things are simpler to
them.

You were trying to make this a paradigm/experience issue and provide
excuses. If you truly want to learn the right way, then empty your cup
and don't make excuses.

That's not meant to be harsh. It's just meant to be advice. :)
When moving to another language, the first year is really spent breaking
old mindsets and philosophies.

Right. So do it instead of making excuses.
Ruby is a very good OOL and it's must
easier to use than other languages. I'm thankful for that.

Ryan and Pharrington provided input into the topic and I thank them.
You did not.

Because I had nothing to add to the technical knowledge that they'd
already shared. But I did have advice that I think needed to be given,
so I gave it.

Best,
 
G

Gary Wright

I was only providing a list in answer to Pharrington. Call it Saturday
night satire. I think I provided most, if not all operating systems
that won't accept a forward slash via path.. but I could have missed one
or two. But, no need to respond to this bit. :)

The important item that I don't think has been mentioned in this
thread is that the Ruby runtime is responsible for converting
forward slash separated paths to the appropriate format for the
underlying OS. So in the statement:

require "foo/baz"

The string is an abstract representation of a relative path. When
Ruby eventually has to touch the filesystem it may have to convert
that path into "foo\baz.rb" or maybe "node:[directory]baz.rb".

The point is that the programmer shouldn't have to worry about
all that in most cases.

Gary Wright
 
M

Marnen Laibow-Koser

Gary said:
I was only providing a list in answer to Pharrington. Call it Saturday
night satire. I think I provided most, if not all operating systems
that won't accept a forward slash via path.. but I could have missed one
or two. But, no need to respond to this bit. :)

The important item that I don't think has been mentioned in this
thread is that the Ruby runtime is responsible for converting
forward slash separated paths to the appropriate format for the
underlying OS. So in the statement:

require "foo/baz"

The string is an abstract representation of a relative path. When
Ruby eventually has to touch the filesystem it may have to convert
that path into "foo\baz.rb" or maybe "node:[directory]baz.rb".

The point is that the programmer shouldn't have to worry about
all that in most cases.

Good to know. I thought this was the case, but was not certain enough
to say it outright.
Gary Wright

Best,
 
A

Alpha Blue

I encountered a particular issue over the last couple of days when I
decided to test trial a package process using Ocra and WxRuby/Wx_sugar.
I already solved the issue but I wanted to get some clarification, or
make sure that I'm performing best practices.

In the case of my issue, wx_sugar has a program called xrcise which
automatically reads xrc source files and creates a ruby file that
attaches listener events and extends some of the events through custom
modules.

After porting my code to a quick app.exe format using Ocra, I noticed
that it would work fine in the directory, but anywhere else on my system
it would not. So, I dug deep into the code and into some external
testing/debugging scripts.

It turned out that one piece of the ruby file that was automatically
generated by xrcise was placing the following statement for loading xml:

xml.load('ui/ui.xrc')

Now, I knew that this was the issue but I wanted to see how the working
directories were truly working on windows with the executable. When
Ocra packages the exe file and you open it, it automatically unpacks the
exe into the temp directory. So, in my case the directory was

C:\users\joel\appdata\temp\ocra43.tmp\src\...etc.

All of the app worked great except for this one piece. When diagnosing
the working directory for this xml.load, the working directory was the
desktop directory where the file was launched. This meant that it was
trying to find a ui directory on the desktop with the xrc source file
within.

So, I changed the ruby file that was created from:

xml.load('ui/ui.xrc')

To: xml.load(File.join(File.dirname(__FILE__),"ui.xrc"))

.. which fixed the issue and forced an absolute path directly to where
the file was located.

Looking at the Ruby api, it says that when using load it resolves to an
absolute path.

So, am I correct to assume that require is realistically for relative
paths and load should be formally used with absolute paths? Given the
issue that just occurred with a file that was created and is heavily
used by other WxRuby people, wouldn't it be more prudent to use only
absolute paths with load statements? Or, is this more of a case by case
basis, depending on whether or not you are packaging/porting your code?

My thanks.
 
R

Robert Klemme

2010/2/1 Alpha Blue said:
So, am I correct to assume that require is realistically for relative
paths and load should be formally used with absolute paths? =A0Given the
issue that just occurred with a file that was created and is heavily
used by other WxRuby people, wouldn't it be more prudent to use only
absolute paths with load statements? =A0Or, is this more of a case by cas= e
basis, depending on whether or not you are packaging/porting your code?

I would make a different distinction:

"require" is for loading library code (libs as parts of the
installation, self written libs as well as gems).

"load" is for explicitly forcing a file load and execution at a define
place in the source code.

Now, I don't know Ocra and hence I can't say anything about it. My
approach is this: I have environment variable RUBYLIB set to an
absolute path where I place my own written libs ("${HOME}/lib/ruby" in
my case). I don't have any gems installed on the system I am working
on so no requirements there. But generally the usage model of
"require" is that there is a list of entry points (partly built into
the interpreter, partly provided by the user e.g. via $RUBYLIB) which
are searched - which also means you generally use only relative paths
with require. This is also true for recursive requires - which can be
autoloads as well. See here for an example:

http://github.com/rklemme/muppet-laboratories/blob/master/lib/animal.rb

I cannot remember when I used "load" the last time - probably because
I do not generate code most of the time and my programs are not that
large that I would need to executed code in a file potentially
multiple times. I'd say, whenever you do this you need to make sure
you provide the path in a way that the script can be found. If you
generate it, you'll have the file name in a variable anyway and so you
can use that. If you need to find it based on different criteria you
need to do whatever it takes to make the path correct.

Turning back to your original example: it looks like what you really
want is to do "require 'ui'" and have a file "ui.rb" located somewhere
in your library path which then consists mainly (or only) of "require
'ui/a'" lines. "a.rb" then would be placed in directory <lib>/ui, i.e.
below the directory which contains file "ui.rb".

Hope that helps.

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
A

Alpha Blue

Robert said:
"require" is for loading library code (libs as parts of the
installation, self written libs as well as gems).

"load" is for explicitly forcing a file load and execution at a define
place in the source code.

Thanks for the clarification Robert and I like your distinction because
it makes more sense to me. With your example in place, I am using
require and load statements correctly then. The only thing I've been
doing with regard to load statements is defining an absolute load path
rather than a relative load path. Code execution in this example is the
loading of an xml source file (xrc) by wx_sugar.
Now, I don't know Ocra and hence I can't say anything about it. My
approach is this: I have environment variable RUBYLIB set to an
absolute path where I place my own written libs ("${HOME}/lib/ruby" in
my case). I don't have any gems installed on the system I am working
on so no requirements there. But generally the usage model of
"require" is that there is a list of entry points (partly built into
the interpreter, partly provided by the user e.g. via $RUBYLIB) which
are searched - which also means you generally use only relative paths
with require. This is also true for recursive requires - which can be
autoloads as well. See here for an example:

This is strange because I don't know why I never thought about doing
this with Ruby. I'm so used to keeping my projects separate and
therefore, I tend to keep the libs separate. However, I could see
defining a libs dir for reusable library classes that I require in
future projects. Then, all I would have to do is require and/or include
the code I need. Ocra does look over the rubyopt variables set at the
time of processing. I'll have to check the $: to see that my custom lib
directories are being set properly and included, but I can definitely
see this being a better way of implementing things later on. I can
privatize and store all my libs on github for safekeeping and rdoc
everything for my own benefit.

Robert this actually helps me out a lot because I want to write my own
custom modules for use with wxruby and I can define the namespaces and
just extend off those modules through dialogblocks when I generate my
elements and xrc source.

I have not looked into autoloads at all. I'll read up on them.
Turning back to your original example: it looks like what you really
want is to do "require 'ui'" and have a file "ui.rb" located somewhere
in your library path which then consists mainly (or only) of "require
'ui/a'" lines. "a.rb" then would be placed in directory <lib>/ui, i.e.
below the directory which contains file "ui.rb".

No, that's not what the issue was in this case. The ui.rb file is
actually a file called xrcframemain.rb which is automatically generated
by xrcise. This is one file that will always change in any application
that is created. So, it's a roaming ruby file depending on which
project I'm in. Inside of this file, there is a custom xml.load
statement being used by wx_sugar to read xml source from an xrc file
that's generated by most GUI designer apps. This xml file contains
information pertaining to GUI element positioning and also ties IDs to
instance variables that will be used in the app, as well as sub-class
element tags that are used to extend into modules. So, together, the
xrcframemain.rb and the ui.xrc files combine into a separate but usable
structure where program code is kept separate from design code.

So, I won't change the requires for this particular file. At the
moment, I'm not having issues with any of my requires. Everything is
working well. However, with your input and suggestions, I am going to
change my whole way of thinking in terms of consolidating lib files for
use with wxruby.
Hope that helps.

Kind regards

robert

It does - my thanks!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,052
Latest member
LucyCarper

Latest Threads

Top