How to work with classes and dependences in ruby - ruby

I have changed this question to better reflect what it is I do not understand.
For example if I try to access the methods in the railties class AppBuilder.
require 'rails/generators/rails/app/app_generator'
g = Rails::AppBuilder.new
puts g.rakefile.inspect
I get an error message activesupport-3.1.3/lib/active_support/secure_random.rb:5:in `': uninitialized constant SecureRandom (NameError)
I do not understand this. Should not each class be "independent" from other classes? Is that not the whole point of object oriented programing?
And now If it is not so more importantly how can I figure out what dependences I need to add? Is it some kind of workflow to solve this? Can I somehow figure out what dependencies to add looking at the documentation? Do this problem have something to do with load path? Can I load all dependences from a gem or rails or whatever? I just don't get it!
doc: http://api.rubyonrails.org/classes/Rails/AppBuilder.html github: https://gist.github.com/rails/rails/blob/master/railties/lib/rails/generators/rails/app/app_generator.rb

there is no easy way to find out which dependencies are used within AppBuilder, cause most of the dependencies are setup somewhere else. so most of the times you need to do some trial and error to get the dependencies right.
the code that you posted has bad style. please get familiar with how to write ruby code properly. buy yourself a book i.e. eloquent ruby or just start reading ruby blogs.
dependencies in ruby is quite simple. every file that you require will be loaded and the load will recurse through the files and then load other requires. the loading will only work if all the required files are on the load path. this load path is similar to your system path and you can add directories to it to tell ruby where to look for files.
in general, there are dedicated entry-points for libraries and their dependencies. those are normally documented, so that if you use them, you get all dependencies right from the beginning. an example for this would be to require 'rails' in order to use rails or require 'active_support/all' if you just want to use active-support. if you wan't to chery-pick files/classes than you are on your own finding out which other classes you need. that part has nothing to do with oop, it's more an dependency-issue (other languages have explicit decleration of dependencies).
in your case, the next step would be to add require "securerandom" to the beginning of your file and then check wich error comes up next.

Related

How do I load files into Ruby?

I was wondering how to load a file from my System Libraries, but I'm not sure how. I was thinking something along the lines of:
require 'gosu'
require "Picture.jpg"
and then having the rest of my code, but every time I try that, I get the error:
No such file to load
I'm not sure if I'm doing something wrong, or there just isn't a way to load a file from my system library into Ruby?
I would suggest you to take close looks at require, load, extend and include.
It will help you to use in your application.
http://ionrails.com/2009/09/19/ruby_require-vs-load-vs-include-vs-extend/

confluence4r add

We use Jira/Confluence as our wiki site. I've had a difficult time trying to figure out how to use the add. I'm guessing i'm missing something very obvious. When I go to this site: https://confluence.atlassian.com/display/DISC/Confluence4r to download the confluence4r file, not sure what I'm supposed to do thereafter. The file contains a module which makes sense why it doesn't do anything when running it. But should I being using the gem install functionality in some way? When I simply try to use it in a ruby script, i get the following error:
conf.rb:15:in `<main>': uninitialized constant Confluence (NameError)
Where I am supplying the information required per the script (URL, user & pass contained the correct values when used):
server = Confluence::Server.new("https://collab.sitename.com")
server.login("user", "pass")
puts server.getSpaces()
Any information how to get the working is appreciated.
Confluence4r isn't distributed as a rubygem, it's just a ruby script you can drop onto your filesystem and reference directly.
If you put Confluence4r.rb in the same directory as your own script, you'd need to require it like this:
require './confluence4r.rb'
You shouldn't need the "confluence" and "confluence-client" rubygems to use confluence4r; it's just a very thin wrapper around the Confluence XML-RPC API.

Utility Classes In Ruby on Rails

This is probably a stupid question, but I'm new to Ruby on Rails and I could use a little guidance. I want to have a helper/utility class that performs a group of network operations and returns results. Where do I put that class and how do I use it.
I've created network_helper.rb in my app/modulename/helpers directory. In my controller when I try to do
myNetworkHelper = ModuleName::NetworkHelper.new
results = myNetworkHelper.getResults
I get an error
undefined method `new' for MyModule::NetworkHelper:Module
I'm sure this is just a misunderstanding of how ruby on rails works. Can I get some clarification?
Would it be better to make this a class instead of a module and put it in libs? And can I add subfolders in libs and have them automatically loaded?
Lib or Classes
Little utility classes like this typically go in the lib folder, though some people prefer to create a folder called classes. Whichever you choose, make sure you import the folder in config/application.rb, as the lib folder is not autoloaded:
config.autoload_paths += %W(#{config.root}/lib)
Concerns
If instead of a utility class, you want to extend some of your models with reusable code, you may also wish to look at the new Rails 4 concerns folders which encourage you to extract reusable modules:
see: How to use concerns in Rails 4
To use new, the thing your calling it on must be a class, not a module. You're using a module. Change module to class in lib/utilities/network_utility.rb.
I cannot verify this at the moment, however I believe one place you can store your custom modules and classes is the lib directory. Alternatively, you should be able to store them in the app directory in the manner you have indicated by adding the following line to your environment.rb:
config.load_paths << File.join(Rails.root, "app", "modulename")
Also, check out Yehuda Katz's answer, which I think not only answers your question better, but also contains some very interesting and useful information and concepts relating to your situation. Hope that helps!
Add your class to app/lib folder instead of lib, so that you don't change autoload paths!
Explanations:
The accepted answer suggests adding the classes to lib.
But according to this discussion:
The lib folder does not belong to the autoload paths since Rails 3.
So it's discouraged to add lib under autoload path. Use app/lib instead.

How can I build a modular command-line interface using rubygems?

I've written a command-line tool for manipulating with genome scaffolds called "Scaffolder". At the moment all the tools I want to use are hard-coded into the library. For instance these tools "validate" or "build" the scaffold. I'd like to split these tools out into their own gems, make it more modular, and to allow third parties to write their own commands.
The ideal case would be that I run "gem install scaffolder-validate" and this gem-bundled command would then be available as part of scaffolder. I know a couple of libraries make it easy to build a command-line interface: thor, commander, gli, .... However I don't think any of them cater for this type of functionality.
My question is how can I use a gem structure to create a module structure for installing these commands? Specifically how can the installed commands be auto-detected and loaded? With some prefix in the gem name scaffolder-* then searching rubygems? How could I test this with cucumber?
So, one thing you can do is to decide on a canonical name for your plugins, and then use that convention to load things dynamically.
It looks like your code is all under a module Scaffolder, so you can create plugins following the following rules:
Scaffolder gems must be named scaffold-tools-plugin-pluginname
All plugins expose one class, named Scaffolder::Plugin::Pluginname
That class must conform to some interface you document, and possibly provide a base class for
Given that, you can then accept a command-line argument of the plugins to load (assuming OptionParser):
plugin_names = []
opts.on('--plugins PLUGINS','List of plugins') do |plug|
plugin_names << plug
end
Then:
plugin_classes = []
plugin_names.each do |plugin_name|
require "scaffold-tools-plugin-#{plugin_name}"
plugin_classes << Kernel.const_get("Scaffold::Plugin::#{plugin_name}")
end
Now plugin_classes is an Array of the class objects for the plugins configured. Supposing they all conform to some common constructor and some common methods:
plugin_classes.each do |plugin_class|
plugin = plugin_class.new(args)
plugin.do_its_thing(other,args)
end
Obviously, when doing a lot of dynamic class loading like this, you need to be careful and trust the code that you are running. I'm assuming for such a small domain, it won't be a concern, but just be wary of requireing random code.
Hm, tricky one. One simple idea I have is that the main gem just tries to require all the others and catches the load error when they are not there and disables the respective features. I do this in one of my gems. If HighLine is present, the user gets prompted for a password, if it isn't there has to be a config file.
begin
require 'highline'
rescue LoadError
highline = false
end
If you have a lot of gems this could become ugly though...

What does the World() method do in ruby?

I'd like to know what does the following line do:
World(::Cucumber::Rails::Capybara::SelectDatesAndTimes)
Because I'm getting
uninitialized constant Cucumber::Rails::Capybara::SelectDatesAndTimes::XPath (NameError)
And I don't understand what it is supposed to do to tell what's wrong :-)
EDIT: I gisted my Gemfile: https://gist.github.com/822480 and my gem list on windows vista 32-bit (https://gist.github.com/822483) and ubuntu maverick 32-bit https://gist.github.com/822491. Both are running ruby 1.8.7. Notice that I'm using this fork of cucumber-rails: https://github.com/johnf/cucumber-rails because my ultimate goal is to get these datetime selectors to work with capybara.
I also found that on Linux I get another error message:
Unable to find '#<XPath::Union:0xb6e078b8>' (Capybara::ElementNotFound)
The World() method isn't one from Ruby, it's one specifically from Cucumber, regrettably they haven't even documented it.
http://rubydoc.info/github/aslakhellesoy/cucumber-rails/master/Cucumber/Rails/World:initialize
In this case, it looks like something it missing from your Environment, maybe Caprybara, please give more info, and share your Ruby/Rails/Cucumber/Bundler/etc versions, and your Gemfile.
World is just an instance of Object that you can use in every step definition, its like a library that you expose without the need to import (or require in every step definition file).
see more at: https://github.com/cucumber/cucumber/wiki/Configuring-the-Scenario-Execution-Context-(World)
(Note that I'm still learning, so this may be wrong.)
A world-level method involves multiple objects versus a class- or object-specific method.
If you are having an issue with calling a world method, then check to see if the world method is specifying an object that can't be found.

Resources