how does 'require' work exactly?

Hi,

I need some help understanding how to track down a "require ‘runt’ " line that is not working.

The runt gem ( http://runt.rubyforge.org/ ) says after you install it you can do the following and this should work.

require ‘runt’

last_thursday = DIMonth.new(Last_of,Thursday)

For me when within a Rails Console I get the following:

Macintosh:myEquity greg$ ruby -v
ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.10.1]

Macintosh:myEquity greg$ ./script/console
Loading development environment (Rails 2.0.2)

require ‘runt’
=> []

last_thursday = DIMonth.new(Last_of,Thursday)
NameError: uninitialized constant DIMonth

    from /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:266:in `load_missing_constant'

    from /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:453:in `const_missing'
    from /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:465:in `const_missing'

    from (irb):2

But if I actually prefix the runt class like as follows it does seem to work:

august = Runt::REYear.new(8)

=> #<Runt::REYear:0x5398c8 @same_month_dates_provided=false, @end_day=0, @end_month=8, @start_day=0, @start_month=8>

I thought if I knew how the ‘require’ works I could then try to fault find why things aren’t working for me here. Any suggestions re how to fault find here?

Thanks

Greg

Hi,

I need some help understanding how to track down a "require 'runt' " line that is not working.

require just loads a file (if it hasn't been loaded before). gem extends that so that it can find gems and so on

The runt gem ( http://runt.rubyforge.org/ ) says after you install it you can do the following and this should work.
     require 'runt'
     last_thursday = DIMonth.new(Last_of,Thursday)

All of those constants are in the Runt module, which is why Runt::REYear works. if you include Runt then you can ditch the prefixes.

For me when within a Rails Console I get the following:

Macintosh:myEquity greg$ ruby -v
ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.10.1]
Macintosh:myEquity greg$ ./script/console
Loading development environment (Rails 2.0.2)
>> require 'runt'
=> []
>> last_thursday = DIMonth.new(Last_of,Thursday)
NameError: uninitialized constant DIMonth
        from /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:266:in `load_missing_constant'
        from /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:453:in `const_missing'
        from /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:465:in `const_missing'
        from (irb):2

But if I actually prefix the runt class like as follows it does seem to work:
>> august = Runt::REYear.new(8)
=> #<Runt::REYear:0x5398c8 @same_month_dates_provided=false, @end_day=0, @end_month=8, @start_day=0, @start_month=8>
>>

I thought if I knew how the 'require' works I could then try to fault find why things aren't working for me here. Any suggestions re how to fault find here?

Everything is working. move along sir.

Fred

require ‘runt’ ==> this isn’t working for me. That is I should be able to just have runt classes recognized (e.g. REYear.new(8)), but such statements per the runt tutorial don’t work…

require 'runt' ==> this isn't working for me. That is I should be
able to just have runt classes recognized (e.g. REYear.new(8)), but
such statements per the runt tutorial don't work...

The runt tutorial is just wrong. require 'foo' won't include Foo into
your namespace. (like I said, that's what include is for)

Fred

can someone clear up for me:

Q1 - When you do a "require " what directories will ruby look for to find that file in? For example is the gem path stored as an environment variable, someone in the ruby installation configuration?

Q2 - Assuming Ruby knows where the GEM path is what are the rules re where it looks within here when you do a require? Do it recursively go through subdirectories for example? Is there any concept of looking relative to the path of the current ruby file from which the ‘require’ is in?

Q3 - Does Rails itself add anything to the mix here to assist? Or do exactly the same principles apply when you’re working out whether you need a “require” in your rails code (as per if it were just a basic ruby application)?

Thanks

can someone clear up for me:
Q1 - When you do a "require <filename>" what directories will ruby look for
to find that file in? For example is the gem path stored as an environment
variable, someone in the ruby installation configuration?

Ruby searches its load path ($:/$LOAD_PATH). ruby gems overrides
require, so that if a 'normal' require fails, rubygems will activate
the appropriate gem (which usually adds the gem's lib folder to the
load path) and tries again. Where gem looks is controlled by a bunch
of environment variables, GEM_HOME, GEM_PATH etc..

Q2 - Assuming Ruby knows where the GEM path is what are the rules re where
it looks within here when you do a require? Do it recursively go through
subdirectories for example? Is there any concept of looking relative to the
path of the current ruby file from which the 'require' is in?

There is no recursiveness so if the load path contains /foo and you
want to load /foo/bar/x.rb then you need to require bar/x. $: by
default contains '.'.

Q3 - Does Rails itself add anything to the mix here to assist? Or do
exactly the same principles apply when you're working out whether you need a
"require" in your rails code (as per if it were just a basic
ruby application)?

It overrides const_missing so that if you get a const_missing for User
it will try and require 'user'. As I said before, require isn't your
problem. if it was the require would throw and you wouldn't be able to
do Runt::REYear.new(8)

Fred

excellent - thanks for explaining Frederick, this is a lot clearer now for me. I can now see that with rubygems active that the "include ‘runt’ " does find the main runt.rb file, and within runt.rb it does a "require “runt/temporalexpression” ".

So the penny hasn’t quite dropped as to why when I’m referring directly to “REYear” this doesn’t work, however “Runt::REYear” does? Is this standard for Ruby that you always have to prefix a classname within a module with the module name? There would be lots of Rails modules no that have classes within modules, and you can typically just refer directly to the classes no?

------temporalexpression.rb------

module Runt

.

.

class REYear

.

.

end

end

Yup, that's just standard ruby. Eg ActiveRecord::Base, ActionView::Base, ActiveResource::Base, ActionController::Base all exist.

Fred