In Ruby, do i require within a class or outside? - ruby

If i want to make a class :
class Foo
#methods here
end
that requires lets say FileUtils
do i do
require 'fileutils'
class Foo
#methods here
end
or
class Foo
require 'fileutils'
#methods here
end

To complement fotanus's answer. Anything defined on a separate file rests in the main namespace, wherever you load or require it from. It does not make difference in terms of scope or namespace. Furthermore, local variables cannot be referenced across files.
So your choice should depend on maintainability. If you write the dependencies on the top of the file, it is easy to know the dependency at a glance. On the other hand, if you require within a certain module, it can make it clear that that dependency is only for the particular module. In the older days, I think the former was preferred, but nowadays, where people use the bundler gem, there is a means to see all the dependencies at a glance, so the motivation for the former may have declined.

It will work either way. require works anywhere, and the FileUtils will be available inside and outside of your class.
By what I have seen on github, it is usually on top - just like most of the other languages, by the way.

Related

Ruby require multiple files without knowing their class names

Let's say I have an Application that requires different files. Each file contains a single purpose "thing". I call it "thing" because I'm unsure if it will be a class or a module.
The First Thing
# things/one.rb
class One
def self.do_it
"I'm the one"
end
end
And the second
# things/two.rb
class Two
def self.do_it
"I'm not the only one!"
end
end
Now I wanna require all files in the thingsdirectory and execute the do_it method. But I wanna do this dynamically - for every thing in things folder without even knowing their Classname.
# app.rb
Dir["things/*.rb"].each {|file| require file }
Keep in Mind: I simply wanna execute the code in the things files - it's not necessary that they are Classes or Modules
You can't reliably do this for a number of reasons, but the most important is that you're under no obligations to declare a single class in any given file, or a class at all. You've got the right idea with loading in all files in a particular directory, but if you need to operate on those there's two ways to crack that nut.
The easiest way is to declare these classes as a subclass of some already known parent. ActiveSupport has the descendents method to reflect on a particular class, that's part of Rails, but you can also do it the hard way if you have to.
The second easiest way is to correlate the names with the classes in them, and then convert filenames to class-names algorithmically. This is how the Rails autoloader works. cat.rb contains Cat, bad_dog.rb contains BadDog and so on.
If you look more closely at how things like Test::Unit work they take the first approach, any declared test subclasses are executed before the Ruby process terminates. It's a fairly simple system that puts no constraints on what the files are called or where and how the classes are declared.
Rails leans towards the second approach where the path communicates intent. This makes finding files more predictable but requires more discipline on the part of the developer to conform to that standard.
They both have merit. Pick the one that works for your use case.

load 'file.rb' versus require 'Module' in Ruby

I am confused about the difference between load 'file.rb' and require 'Module'. At Learn Ruby the Hard Way, the example of how to use a module is set up with two files (mystuff.rb and apple.rb):
mystuff.rb
module MyStuff
def MyStuff.apple()
puts "I AM APPLES!"
end
end
apple.rb
require 'mystuff'
MyStuff.apple()
However, when I run apple.rb, either in the Sublime Text console, or with ruby apple.rb, I get a Load Error. I have also tried require 'MyStuff', and require 'mystuff.rb', but I still get the Load Error.
So, I switched the first line of apple.rb to load 'mystuff.rb', which allows it to run. However, if I edit 'mystuff.rb' to be a definition of class MyStuff as opposed to a module MyStuff, there is no difference.
For reference, the Load Error is:
/Users/David/.rvm/rubies/ruby-2.0.0-p353/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in require': cannot load such file -- mystuff (LoadError)`
I've peeked into kernel_require.rb and looked at the require definition, but since I'm a Ruby Nuby (indeed, a programming newbie), it was a little overwhelming. Since Learn Ruby the Hard Way hasn't been updated since 2012-10-05, there've probably been some syntax changes for modules. Yes?
require searches a pre-defined list of directories, as discussed in What are the paths that "require" looks up by default?. It's failing because it can't find the mystuff.rb in any of those directories.
load, on the other hand, will look for files in the current directory.
As for:
However, if I edit 'mystuff.rb' to be a definition of class MyStuff as
opposed to a module MyStuff, there is no difference.
I'm not sure I understand what you mean by "no difference". If you mean that the require and load continue to fail and succeed, respectively, that makes sense, as the require failure is independent of the content of the file contents and the code you're testing behaves the same independent of whether Mystuff is a class or a vanilla module.
You can solve this easily by changing
require 'mystuff'
to
require_relative './mystuff'

In Ruby, is there a way for classes to be accesible by package, or are all of the classes to be written in the same file of code?

I'm using Netbeans to program in Ruby and I can't seem to access other classes I write from the main class in Ruby until I place that code inside the main class itself. Is there a way to fix this so that it works like Java classes do?
If I understand you correctly, you are looking to import a class you wrote in a separate file into your current file. If this is what you are looking to do, take a look at require_relative
# cow.rb
class Cow
def moo
'Moooooooo'
end
end
# main.rb
require_relative 'cow.rb'
milford = Cow.new
puts milford.moo #=> 'Moooooooo'
Things to look out for is that require_relative searches for the file in the current location of the file you call it in. For instance:
# If cow.rb is in folder 'animals'
require_relative 'animals/cow.rb' #=> Fine
require_relative 'cow.rb' #=> LoadError
I would suggest finding some good tutorials on Ruby or finding a beginners book. Some of them are even available online like Programming Ruby The Pragmatic Programmer's Guide. This question covers some pretty basic Ruby concepts.
Also, I would not suggest using Netbeans since they cut out their support for Ruby. This is fine if you want to continue to use the old version of Netbeans but you will soon find it lacking support for newer Ruby versions.
For one thing, Ruby has no concept of "packages". There are files, and modules. To import all of the global variables, constants, modules, and classes from a file in the same directory, type:
require_relative "myfile.rb"
You can now use any classes, modules, constants, and global variables defined in myfile.rb in your code.

Ruby class loading mechanism

I'm beginning with the Ruby programming language and I'm interested in understanding it in depth before I start studding the Rails framework.
I'm currently a little disappointed because everybody seams to care only about the Rails framework, and other aspects of the language are just not discussed in depth, such as its class loading mechanism.
Considering that I'm starting by doing some desktop/console experiments, I would like to better understand the following matters:
Is it a good practice to place each Ruby class in a separate Ruby file? (*.rb)
If I have, let's say .. 10 classes .. and all of them reference each other, by instantiating one another and calling each other's methods, should I add a 'require' statement in each file to state which classes are required by the class in that file? (just like we do with 'import' statements in each Java class file?)
Is there a difference in placing a 'require' statement before or after (inside) a class declaration?
What could be considered a proper Ruby program's 'entry point'? It seams to me that any .rb script will suffice, since the language doesn't have a convention like C or Java where we always need a 'main' function of method.
Is class loading considered a 'phase' in the execution of a Ruby program? Are we supposed to load all the classes that are needed by the application right at the start?
Shouldn't the interpreter itself be responsible for finding and loading classes as we run the code that needs them? By searching the paths in the $LOAD_PATH variable, like Java does with its $CLASSPATH?
Thank you.
In general terms, it's a good practice to create a separate .rb file for each Ruby class unless the classes are of a utility nature and are too trivial to warrant separation. An instance of this would be a custom Exception derived class where putting it in a separate file would be more trouble than its worth.
Tradition holds that the name of the class and the filename are related. Where the class is called ExampleClass, the file is called example_class, the "underscored" version of same. There are occasions when you'll buck this convention, but so long as you're consistent about it there shouldn't be problems. The Rails ActiveSupport auto-loader will help you out a lot if you follow convention, so a lot of people follow this practice.
Likewise, you'll want to organize your application into folders like lib and bin to separate command-line scripts from back-end libraries. The command-line scripts do not usually have a .rb extension, whereas the libraries should.
When it comes to require, this should be used sparingly. If you structure your library files correctly they can all load automatically once you've called require on the top-level one. This is done with the autoload feature.
For example, lib/example_class.rb might look like:
class ExampleClass
class SpecialException < Exception
end
autoload(:Foo, 'example_class/foo')
# ...
end
You would organize other things under separate directories or files, like lib/example_class/foo.rb which could contain:
class ExampleClass::Foo
# ...
end
You can keep chaining autoloads all the way down. This has the advantage of only loading modules that are actually referenced.
Sometimes you'll want to defer a require to somewhere inside the class implementation. This is useful if you want to avoid loading in a heavy library unless a particular feature is used, where this feature is unlikely to be used under ordinary circumstances.
For example, you might not want to load the YAML library unless you're doing some debugging:
def debug_export_to_yaml
require 'yaml'
YAML.dump(some_stuff)
end
If you look at the structure of common Ruby gems, the "entry point" is often the top-level of your library or a utility script that includes this library. So for an example ExampleLibrary, your entry point would be lib/example_library.rb which would be structured to include the rest on demand. You might also have a script bin/library_tool that would do this for you.
As for when to load things, if there's a very high chance of something getting used, load it up front to pay the price early, so called "eager loading". If there's a low chance of it getting used, load it on demand, or leave it "lazy loaded" as it's called.
Have a look at the source of some simple but popular gems to get a sense of how most people structure their applications.
I'll try to help you with the first one:
Is it a good practice to place each Ruby class in a separate Ruby file? (*.rb)
It comes down to how closely related those classes are. Let's see a few examples. Look this class: https://github.com/resque/resque/blob/master/lib/resque.rb
, it "imports" the functionality of several classes that, although they work together, they are not closely related to be bundled together.
On the other hand, take a look at this module: https://github.com/resque/resque/blob/master/lib/resque/errors.rb. It bundles 5 different classes, but these do belong together since they are all essentially representing the same.
Additionally, from a design standpoint a good rule of thump could be asking yourself, who else is using this class/ functionality (meaning which other parts of the code base needs it)?
Let's say that you want to represent a Click and WheelScroll performed by a Mouse. It would make more sense in this trivial example, that those classes be bundled together:
module ComputerPart
class Mouse; end
class WheelScroll; end
class Click; end
end
Finally, I would recommend that you peruse the code of some of these popular projects to kind of get the feeling how the community usually make these decisions.
1.) I follow this practice, but it is not necessary, you can put a bunch of classes in one file if you want.
2.) If the classes are in the same file, no, they will all be accessible when you run the script. If they are in separate files then you should require them, you can also require the entire directory that the file(self) is in.
3.)Yes, it should be at the top of the file.
4.) In ruby everything descends from the Main object, the Interpreter just handles creating it for you. If you are writing OO ruby and not just scripts, then the entry point will be the init method of the first class you call.
5.) Yes, before the program runs it loads up all the dependencies.
6.) I think it does this, all you have to do is require the proper files at the top of the files, after that you can use them as you wish without having to implicitly load them again.

Ruby, including module in current directory

I am currently working through the Well Grounded Rubyist. Great book so far. I am stuck on something I don't quite get with ruby. I have two files
In ModuleTester.rb
class ModuleTester
include MyFirstModule
end
mt = ModuleTester.new
mt.say_hello
In MyFirstModule.rb
module MyFirstModule
def say_hello
puts "hello"
end
end
When I run 'ruby ModuleTester.rb', I get the following message:
ModuleTester.rb:2:in <class:ModuleTester>': uninitialized constant ModuleTester::MyFirstModule (NameError)
from ModuleTester.rb:1:in'
From what I have found online, the current directory isn't in the the namespace, so it can't see the file. But, the include statement doesn't take a string to let me give the path. Since the include statement and require statements do different things, I am absolutely lost
as to how to get the include statement to recognize the module. I looked through other questions, but they all seem to be using the require statement. Any hints are greatly appreciated.
You use require to load a file, not include. :-)
First, you have to require the file containing the module you want to include. Then you can include the module.
If you're using Rails, it has some magic to automagically require the right file first. But otherwise, you have to do it yourself.
You need to require the file before you can use types defined in it. *
# my_first_module.rb
module MyFirstModule
def say_hello
puts 'hello'
end
end
Note the require at the beginning of the following:
# module_tester.rb
require 'my_first_module'
class ModuleTester
include MyFirstModule
end
mt = ModuleTester.new
mt.say_hello
The require method actually loads and executes the script specified, using the Ruby VM's load path ($: or $LOAD_PATH) to find it when the argument is not an absolute path.
The include method, on the other hand actually mixes in a Module's methods into the current class. It's closely related to extend. The Well Grounded Rubyist does a great job of covering all this, though, so I encourage you to continue plugging through it.
See the #require, #include and #extend docs for more information.
* Things work a bit differently when using Rubygems and/or Bundler, but getting into those details is likely to confuse you more than it's worth at this point.

Categories

Resources