Now, I've used Rails enough to know what the rails command does, but how it does it interests me.
The bin/rails file (from github) is as follows:
#!/usr/bin/env ruby
begin
require "rails/cli"
rescue LoadError
railties_path = File.expand_path('../../railties/lib', __FILE__)
$:.unshift(railties_path)
require "rails/cli"
end
As far as I know (and please correct me if I'm wrong), require doesn't run code, just loads classes etc.
I could also not find the rails directory in the root of them gem, so I'm a little confused where that's hiding as well.
Thanks.
require does run code. This will include any code outside of any classes and modules in the file being required plus any executable code in classes and modules that is outside of method declarations. As neutrino has said, the ruby interpreter is running the code in the file being required in order to define the classes in the source. However this might be a bit clearer if you try it out with something that has an obvious side effect like a puts statement.
Try this as a simple example. Create a file hello.rb containing puts "Hello World" then go into irb:
irb(main):001:0> require 'hello'
Hello World
=> true
Next, try this example of a simple class with some executable code in its body. Create a file hello2.rb containing:
class Hello
puts "class Hello being defined"
end
then require this from irb:
irb(main):001:0> require 'hello2'
class Hello being defined
=> true
Going back to bin/rails, take a look at the source for rails/cli in Github to follow the chain of how it works.
All ruby code is executable code. Class/module/method definitions are also executed by the interpreter, so when you say that require loads classes, it's true because loading a class means executing its code :)
Here is the file you are looking for: cli.rb. It's in railties.
Related
I am trying to write some tests for a Poker application I've written in Ruby. I get a cannot load such file -- test_car (LoadError) error when I try to run my tests however. This is what my file directory structure looks like:
Poker
lib
Card.rb
Player.rb
Game.rb
Test
test_card.rb
At the top of test_card.rb, I have require 'Card', but I am not sure how to load it properly.
Typically in a Ruby project you create a test_helper.rb file that sets up the load path for you. I would recommend organizing things like this:
Poker
lib
card.rb
player.rb
game.rb
test
card_test.rb
test_helper.rb
In test_helper.rb:
$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))
Then in card_test.rb:
require_relative "test_helper"
require "card"
Also note that the convention in Ruby is to use all-lowercase for filenames.
You should describe the path while you are running your tests through I flag, as shown in the following line of code:
ruby -I../lib/ test_card.rb
.. takes you to the parent folder - in your case, that is root of your Poker application.
I'll explain my situation.
Here is my file tree in my rails application :
lib/my_module.rb
require 'my_module/my_file'
module My_module
end
lib/my_module/my_file.rb
class Tweetag::Collector
(...)
end
I've made a ruby script that I've put in config/jobs/
I really don't understand how I am supposed to require the file my_file.rb in this file.
require '../../my_module/my_file.rb'
It gives me `require': cannot load such file
Same error with just require 'my_module' which is what I do in my controllers...
Someone here to explain to me ? Thanks a lot
You can autoinclude everything under the lib folderand avoid these problems:
Type this your file in config/application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
If you want to require only a specific file then,
do something relative to Rails root like this
for example: --
lib/plan.rb
module Plan
...some code...
end
and if you want to require it only in some model, say app/models/user.rb
do in user model
require "#{Rails.root}/lib/plan"
class User < ActiveRecord::Base
include Plan
end
if you want it to be available everywhere
one solution is given by #VecchiaSpugna
or you can create a ruby file in config/initializers folder
and require all file over there one by one
OR
try this
require '../../my_module/my_file'
instead of
require '../../my_module/my_file.rb'
You don't need to specify extension for a file in require.
I think there are two solutions.
1) Add the lib path to the search path.
In ruby:
$:.unshift('../../my_module/lib')
Then you can require 'my_module.rb'
I think Vecchia Spugna answer is the rails-version of my ruby-answer. (I'm not familiar with rails).
2) Another solution:
In your lib/my_module.rb you require my_file. This file is located relative to your my_module.rb? Then use require_relative:
require_relative './my_module/my_file'
Just chiming in because it took me forever to figure this out because very little solutions worked.
• I had to use plain old require. I put it in the config/application.rb file.
patching_file_path = File.expand_path("./lib", Dir.pwd)
Dir[patching_file_path+'/*.rb'].each {|file| require file }
• I also put a temporary puts "I'm Working! in the file I'm trying to require so I can check the console to see if it's actually loading.
• Also, if you're using spring loader, before you start your console you should do bin/spring stop in your terminal before you start your rails console. Otherwise, it won't load new files.
Similar to require_relative,
# inside lib/my_module.rb
require File.expand_path('./my_module/my_file', File.dirname(__FILE__))
This expands the path of current file directory and add the relative file path to be required.
I'm writing some Rails code that I want to be both 1.8.7 and 1.9 compatible. In a couple different files, I do some CSV parsing, so I currently have the following requires line in each file:
if RUBY_VERSION < "1.9"
require "rubygems"
require "fastercsv"
CSV = FCSV
else
require "csv"
end
To avoid all the duplication, though, this block should probably live in a single place. Where's the best place to put it? Is application.rb the right place?
I'd put it in an initializer config/initializers/csv.rb. This is loaded into rails automatically, and does not mix into the load path (so you don't have to bother about the file name).
Just be aware that some loading mechanisms do not do a "require" but just run the file in the loader context, so if you get an exception, you may not deal with it in the usual way.
I have some additional scripts that I've written outside of my Rails 3.1.x app, however the time has come to pull data from the database of the Rails app directly rather than utilizing some exports of the data.
To this end, I'd like to integrate the scripts into my rails app. Hitherto I've run rake tasks based on methods in the models such as having this in my lib/taks/app.rake:
desc "Does something."
task :do_some_things => :environment do
ModelName.some_method
ModelName.another_method
end
If I were to place my scripts essentially into lib, would I be able to call these from a rake task? Or would I need a calling method in the model that would require lib/my_script.rb?
I have attempted to write a task like this:
task :run_me => :environment do
`bundle exec lib/script.rb`
end
Then when this executes and I have a require within that script.rb (require 'lib/another_script.rb') I end up getting "cannot load such file" errors.
I'm obviously approaching this the wrong way at present.
It seems as though I should simply have a method invocation in the rake task that would then call the supporting scripts under /lib or elsewhere (wherever would be most appropriate).
my preferred way of handling this sort of thing is as follows:
wrap each script in its entirety in a module with one action method
place the file which contains the method-wrapped script within lib/ (you can put multiple method-scripts in one file, or keep them one-per-file
require everything within lib in your Rakefile
within the rake task, include the module and call the method
so, in very simple terms:
# lib/foo.rb
module Foo
def bar
puts "called me"
end
end
and:
# Rakefile
require File.expand_path('../config/application', __FILE__)
Dir[
File.expand_path(Rails.root.join 'lib', '**', '*.rb')
].each {|f| require f}
desc "does bar from lib"
task :do_bar do
include Foo
bar
end
I think your problem stems from not requiring the proper path to your lib scripts. Instead of doing require 'lib/another_script.rb' from your script (which lives in lib), do something like require File.expand_path(File.dirname(__FILE__)) + '/another_script'. Expanding the path will give you the full path to the script, so ruby shouldn't have any problem loading the file.
So there's this great plugin I've gotten used to using in my Rails 2 projects called Bootstrapper. It essentially duplicates the functionality of the seeds.rb file, but I like it because it lets you break up your bootstrap process into concise chunks.
Anyway, I've gone so far as to fork the project and attempt to turn it into a Rails 3 gem. I've been able to get the gem to initialize and register the rake tasks and generators OK. However, I'm running into a problem with the Bootstrapper class itself. It won't load in the Rails project unless it's in a module.
That is, if I place the Bootstrapper class in a file by itself and require that file in my Railtie, then in my Rails app, it can't find the Bootstrapper class. If I put the class in a module and call Bootstrapper::Bootstrapper everything is peachy.
The code that actually requires the Bootstrapper class is this:
ActiveSupport.on_load :active_record do
require 'bootstrapper/bootstrapper'
end
The source is available here:
http://github.com/jrmehle/bootstrapper/tree/make_gem
Autoload paths actually has an annoying feature of following filesystem paths. For example in your lib or extras (depending on what you autoload) you might have the following file structure:
lib/bootstrapper/bootstrapper.rb
# in this case, Bootstrapper::Bootstrapper.class = Class in rails c
# ie: you don't get a NameError exception
More specifically,
lib/bootstrappers/bootstrapper.rb
# Bootstrapper::Bootstrapper => NameError
# Bootstrappers::Bootstrapper => works
If you really want the other way, you can move everything into your lib/bootstrapper.rb source file but meh, I don't like doing that, that's not how gems are organized. In rails3, you'll find the autoloading pretty nice once you use modules everywhere (which can be painful).
Rails3 uses /extras instead of /lib but it's not required, it's just the default (commented out) from rails new. To switch, you just autoload extras instead of lib.