trying to require active_support in gem - ruby-on-rails

I have a ruby gem and I want to use the Hash.from_xml method in the gem that is included in rails active_support module. I have the below code in my gemspec:
gem.add_dependency 'active_support', '~> 3.0.0'
However, when I build and install the gem locally, run irb, require the gem, I am not seeing the methods from active support included?
Any suggestions on what I am doing wrong or how to debug? Thanks!

You need to require the methods you need from ActiveSupport; they aren't added by default.
As Yevgeniy mentioned in a comment, the way to do this is require 'active_support/all' if you need everything - or if, for example, you want only the Hash extensions then use require 'active_support/core_ext/hash'. Note that this usually doesn't go in the gemspec, but rather in whatever file your gem uses to set itself up.
Perhaps even better would be to require the required ActiveSupport files in the actual files needing them, but that's a matter of taste.

Related

Coveralls.io: How to load the gem 'coveralls' when developing a gem itself (not an app)?

I want to use Coveralls.io for my gem Headhunter that I'm developing at the moment. The doc says, I should simply add
gem 'coveralls', require: false
to the project, but as far as I know, this isn't the right way to load gems within another gem. Instead, stuff like that should happen in the .gemspec file. So I tried to add it like this:
s.add_development_dependency('coveralls', '>= 2.0')
But this doesn't work - it breaks my gem's whole functionality:
$ rake
/Users/josh/.rvm/rubies/ruby-2.0.0-p353/bin/ruby -S rspec ./spec/headhunter/css_hunter_spec.rb ./spec/headhunter/css_validator_spec.rb ./spec/headhunter/html_validator_spec.rb
/Users/josh/Documents/Work/MuheimWebdesign/headhunter/lib/headhunter/css_validator.rb:6:in `<class:CssValidator>': undefined method `full_gem_path' for nil:NilClass (NoMethodError)
This is the file that breaks:
require 'net/http'
require 'nokogiri/xml'
module Headhunter
class CssValidator
VALIDATOR_PATH = Gem.loaded_specs['headhunter'].full_gem_path + '/lib/css-validator/'
So Gem.loaded_specs['headhunter'] isn't available anymore, no idea what's going on here.
What's wrong here?
I was wondering the same and I just got it working.
You need to add:
spec.add_development_dependency "coveralls", "0.7.0"
to your .gemspec (0.7.0 is the coveralls gem latest version as the time of writing this)
make sure to run bundle installsuccessfully
and add:
require 'coveralls'
Coveralls.wear!
to the beginning of your spec_helper.rb or test_helper.rb, before requiring anything else.
Hope this helps.

Requiring a gem's assets from another gem

I am creating a gem that will contain the foundation-rails gem along w/ some common variables that are used across my applications. I have created a stylesheet at vendor/assets/stylesheets/foundation.scss. I load this from within my application as such
Gemfile
gem 'foobar-foundation-rails', path: '...'
app/assets/stylesheets/application.css
//= require foundation
This is a good starting point but how do I include the foundation-rails gem's stylesheet from within this file? I am unsure how to reference another gem's assets
I think the best approach is to put the responsibility for the require statements in your rails app's javascripts file. This is most likely not functionality you want to bury in a gem, as it hides what is happening.
Then make sure you require your gem's css file before the foundation-rails require. However you should put a dependency requirement in your gem's gemspec file to ensure that the foundation-rails gem will be installed by bundler when your gem is installed.
Also you may have to "namespace" your gems style sheet in order to avoid namespace collisions.
vendor/assets/stylesheets/foobar_foundation_rails/foundation.css
Which would change the require in your stylesheet file to
require 'foobar_foundation_rails/foundation.scss'
Lastly, the naming of a gem establishes how the gem gets required. When you use dashes Rails expects things to be required, and hence your gem's directory structure to follow
lib/foobar/foundation/rails
As opposed to an underscore naming foobar_foundation_rails
lib/foobar_foundation_rails
Unless you're going to build an "extension" to the foundation-rails gem, which would need to be called foundation-rails-foobar, you may want to go with the underscore syntax to save yourself some require headaches. The devise gem is a good example of extension gems.

When do you need a require in a rails Gemfile?

In my gemfile I have things like:
gem 'net-sftp', '2.1.1', :require => 'net/sftp'
gem 'backup', '3.0.27'
gem 'watu_table_builder', :require => 'table_builder'
gem 'browser', '0.1.6'
When in a Gemfile do you need a require? I've also found things like :require => false. Help?
If you omit the :require option, by default Bundler will attempt to require the gem by using the standard name-to-file conversion rule:
dashes are considered namespace separators and underscore classname separators
It means that the following gem statements
gem 'net-sftp'
gem 'backup'
gem 'foo_bar'
are equivalent to
gem 'net-sftp', require: 'net/sftp'
gem 'backup', require: 'backup'
gem 'foo_bar', require: 'foo_bar'
This works well if the gem author has followed the standard conventions. But in some cases, for a variety of reasons, this doesn't happen.
For instance, there are gems called foo-bar where the main filename is /foo_bar.rb or even /foo.rb. In this case you provide the :require option to tell Bundler which file you want to require.
Finally, require: false is used when you want a gem to be part of the bundle, but you don't want Bundler to load it by default.
This is useful, for instance, to lazy-load a gem in case it is used only in certain circumstances. Think about a rake task that includes a heavy gem. You don't want your application to load it on boot, but it needs to be part of the bundle or it will not be found.
In this case you pass the option require: false. Then, in your rake task you will require it manually as usual
require 'library'
The library will be loaded only when the task is invoked, not in the normal application execution.
A good example is whenever. The library must be part of the bundler because it must be bundled when you deploy the app, but it is intended to be run as a command line script. For this reason, you don't want Bundler to require it when the Rails application is started.
There are cases where you use groups instead of require: false.
See also the official Bundler documentation for require.
You need a :require if the name of the file that's required to activate the gem can't be inferred from the gem's name. Ruby convention is to name your gem the same thing as the "require" statement you should use, but not everything follows the convention.
:require => false disables automatic requiring by Bundler, so you'd need to use require 'foo' manually to use the code in foo. This is mainly useful if a gem is large or expensive to activate and only used in certain cases.
This is often used if the name of the library to require is different than the name of the gem. In your case it would download the gem 'watu_table_builder', but would call 'table_builder'.
require specifies other files that would be required on requiring this particular gem.
Documentation says
Each gem MAY specify files that should be used when autorequiring via
Bundler.require. You may pass an array with multiple files, or false
to prevent any file from being autorequired.
Refer to this for whole documentation

Remove ActiveRecord from Rails 3 application

I have read previous threads on this topic, but the solutions I've found there have not solved my problem. I have a rails 3.2.9 application that does not do database access - it uses an HTTP Rest protocol to another application to access persistent data. The app runs OK in a local test environment with "rails server" using WEbrick, but fails to run with Nginx/Passenger with the error "* Exception LoadError in application (Please install the sqlite3 adapter: gem install activerecord-sqlite3-adapter (sqlite3 is not part of the bundle. Add it to Gemfile.))". From the stack trace it would appear that ActiveRecord wants to eagerly establish a database connection in code that executes prior to the request being processed. I have tried to follow the instructions to remove ActiveRecord from my dependencies with no luck. I generated with --skip-activerecord, which produced an application.rb like this as expected:
require File.expand_path('../boot', __FILE__)
# Pick the frameworks you want:
# require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "sprockets/railtie"
require "rails/test_unit/railtie"
There are no references to activerecord or active_record anywhere in my application except in the gemlock file created by bundler, in comments and in readme. Bundler reports ActiveRecord as a dependency, and 'bundle viz' reports rails itself as being the gem requiring ActiveRecord. Any suggestions or advice would be most welcome.
In response to eric's question, here is my Gemfile
source 'https://rubygems.org'
gem 'rails', '3.2.9'
group :assets do
gem 'sass-rails', '~> 3.2.3'
gem 'coffee-rails', '~> 3.2.1'
gem 'uglifier', '>= 1.0.3'
end
gem 'jquery-rails'
As you have discovered Rails itself has ActiveRecord listed as a dependency in it's Gemspec. The setup you have archived so far is the standard way of removeing ActiveRecord from Rails. If you really want to go further and also remove the gem you will, most likely, have to fork the Rails gem and remove the dependency in it's Gemspec.
It might be that simple, but you might also find that there is additional glue code in Rails to tie ActiveRecord in and you will have to remove that as well. All in all I'm wondering if its worth it.
If you don't need ActiveRecord you have already prevented it from effectively loading. Some parts might still load, but most of it wont. The win in memory footprint/performance against the time you will spend removing a core Rails feature makes me wonder if you are not looking at the wrong framework for your needs?
If you have requirements that are so tight that Rails is still to heavy you should probably look at Sinatra or similar instead. You could also stick with Rails and do a custom Rack middleware stack to keep just the parts of the call stack that you need.
I hope this gave you some guidance to, if not a viably solution, some alternatives to fullfil the higher concerns, since there is no reason in it self to remove the ActiveRecord gem.

how to set gem dependencies without having to declare them on the Gemfile that uses it?

I'm building a gem locally, suppose it name is "MyGem".
Now suppose that MyGem depends on other already built gem, for example "cancan".
So, i've added in my mygem.gemspec the line:
add_runtime_dependency("cancan")
Here is the problem: if I installl MyGem into a new project by adding it into my gemfile like this:
gem "mygem", :path => "path/to/my/local/gem"
then this new project is not being able to use cancan methods, and I have to explicity declare cancan on the new project gemfile in order to use it.
I tried also using gemspec method, but didn't solve my problem either.
Any ideas?
Update
I just wanted to add that when i only have myGem declared in my new application gemfile, after I run bundle install all the dependencies are installed.
That is, if i run gem list the "cancan" gem is displayed, but I still can't access it methods from the application level.
Thanks for the help.
Ok, i've solved this. I'm not sure if this is the best solution but it did work.
Making the application level developer to explicity add the dependencies in his gemfile didn't make any sense. So, as the gems did were being installed, i just required all the gem dependencies in my my_engine.rb file inside my gem.
Following the example, in my my_engine.rb I added the following line
require "cancan"
And that'it...
Even better you could do:
autoload :CanCan, "cancan"
So the module would be loaded only when it is called.
And even better than that, you could load only the file from cancan that you are using (maybe you don't need to load all of it).
You can add that line in you my_gem.rb file or your engine.rb file if you are using engines.
That worked for me, I hope this help someone.
Use add_dependency instead of add_runtime_dependency (this may help with cancan) then run bundle update on your new project.
Does the "cancan" gem name actually match the name to be require'd?
Example for yajl-ruby gem:
Gem::Specification.new do |s|
s.name = %q{yajl-ruby}
...
But when require'ing the library, you'd use a different string:
require 'yajl'
That means in your Gemfile, you have to explicitly require the dependency (which you said you wanted to avoid).
gem 'yajl-ruby', '>=1.0', :require => 'yajl'
To avoid needing to do this, and if you're the author of the "cancan" dependency, you should make the gem name matches the require name.
The only alternative I can think of is require'ing the dependency directly in one of your source files (like you did in your solution).

Resources