Can I use shared gem in rails directory? - ruby-on-rails

I want to use one gem installed in system directory at a Rails project.For a certain reason, I cannnot add it to Gemfile and bundle install.Basicaly, I use bundler.
I want to do like this,
require 'gem_installed_in_vendor/bundle'
require 'gem_installed_in_system'
I wonder removing disable_shared_gems option help my hope,and I delete it from .bundle/config.But,it doens't work hopely.
output of bundle config is,
Settings are listed in order of priority. The top value will be used.
path
Set for your local app (/Users/my_name/works/thisApp/.bundle/config): "vendor/bundle"
and which gem's output is,
/Users/my_name/.rbenv/shims/gem

Related

Bundler is deprecating bundle console in favor of bin/console. Can anyone provide more clarity as to how bin/console should work?

I have a custom ruby gem that relies heavily on bundle console. Nothing special or fancy, just an interactive console with the set of gems defined by the Gemfile included. We use the console a lot during development.
Currently when I run the command, I receive the following deprecation message:
[DEPRECATED] bundle console will be replaced by bin/console generated by bundle gem <name>
Digging around in the bundler docs I found the following explanation:
The bundle console will be removed and replaced with bin/console.
Over time we found bundle console hard to maintain because every
user would want to add her own specific tweaks to it. In order to
ease maintenance and reduce bikeshedding discussions, we're removing
the bundle console command in favor of a bin/console script
created by bundle gem on gem generation that users can tweak to
their needs.
Can anyone with knowledge provide a more detailed explanation? This gem currently does not have a bin directory. I'm happy to make one, I'm just not sure what should be in the file. Running bundle gem as described in the note above raises an error (as expected).
This is the file that is generated at bin/console:
#!/usr/bin/env ruby
require "bundler/setup"
require "(your gem name here)"
# You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like.
# (If you use this, don't forget to add pry to your Gemfile!)
# require "pry"
# Pry.start
require "irb"
IRB.start(__FILE__)
You can see the template in the rubygems GitHub repo.

How to use gems locally?

I would like to use gems 'better_errors' and 'binding_of_caller' for my debugging in rails app, but i DON'T want to include those in Gemfile. Is it possible to do? My first thought was to simply
gem install better_errors
gem install binding_of_caller
but it doesnt work, i mean installation finishes without problems, but thats it, gem doesnt seem to work at all when i run my app on localhost. Do I need some kind of config set, anybody?
but i DON'T want to include those in Gemfile. Is it possible to do?
Yes, it is possible. You can just download the respective directories in desire folder (ex. lib) and add that gem class in your initializer so it will be loaded at the time of starting. Configuration varies as per gem.
My first thought was to simply .... but it doesnt work,
Ofcourse, it wont. How can your rails app magically detects without knowing it that you have better way to show error. It is simply saying like you have cancer formula and doctors automatically applied that formula to there patient without you telling them. There should be some commucaition between two parties rails-app and gem so they can coordinate and work better.
Do I need some kind of config set, anybody?
Yes, explained above.
i dont want to force those gems on my coworkers. KRUKUSA any more details? // said in comment
Yes, including this gems in your rails app can do this job. This extension will be available automatically to your worked. (no force applied :P)
it looks like all you want to not show those gems to other co-worker, if so, you can use this trick with git.
To achieve this thing, first simply add the gems in your gemfile, run bundle and then make it untrackable with git. You can put Gemfile and Gemfile.lock in your .gitignore file. or you can add the first add the gems and mark it ignore with below command. Read more here
git update-index --assume-unchanged Gemfile Gemfile.lock
Another possibility would be to create your own environment and use it accordingly.
Have your own configuration for myenv:
$ cp config/environments/{development,myenv}.rb
In config/database.yml, add the environment myenv and use the same config as development:
development: &development
<rest of the code you have on config/databases.yml>
...
myenv:
<< *development
In Gemfile add your custom gems to use on your mydev group:
group :myenv do
gem 'better_errors'
gem 'binder_of_caller'
end
Run rails and rake with RAILS_ENV like this: RAILS_ENV=myenv rails c
The advantage of this approach is that you still get the updates from Gemfile from the repo, and if you need to add a gem in the Gemfile for everybody to see, you still can.
Also, nobody will see the gems you installed inside the myenv group in your Gemfile.

How to require a gem in .irbrc without needing to also add it to a Rails Gemfile?

I've added awesome_print to my ~/.irbrc file like so:
require 'ap'
Inside a Rails project directory, if I run irb it loads the gem fine, because I've already installed the gem locally. But if I run rails console, it spits out this error:
cannot load such file -- ap
How can I resolve this? I am guessing that it's looking for the gem in the app's Gemfile, but I don't want to add it to the Gemfile because I don't want other developers requiring that dependency. I only want to use awesome_print on my machine.
I am also using rbenv, if that is of any help.
There is this trick.
What you need to do is
# Copy the definition of the debundle! method into your ~/.irbrc
# Call 'debundle!' from IRB when you need to.
(as explained at the top of the file)
The text as it appears on the referred to site:
debundle.rb allows you to require gems that are not in your Gemfile when inspecting
programs that are run with Bundler.
Use at your own risk!
Paste the code of debundle.rb and you are done! A good place would be your .irbrc file
before requiring irbtools.
The code is directly taken from pry-debundle.
Please look there for any further information. This repo exists to simplify debundling
without using the pry repl.

How does load differ from require in Ruby?

Is there any major difference between load and require in the Ruby on Rails applications? Or do they both have the same functionality?
require searches for the library in all the defined search paths and also appends
.rb or .so to the file name you enter. It also makes sure that a library is only
included once. So if your application requires library A and B and library B requries library A too A would be loaded only once.
With load you need to add the full name of the library and it gets loaded every time you
call load - even if it already is in memory.
Another difference between Kernel#require and Kernel#load is that Kernel#load takes an optional second argument that allows you to wrap the loaded code into an anonymous empty module.
Unfortunately, it's not very useful. First, it's easy for the loaded code to break out of the module, by just accessing the global namespace, i.e. they still can monkeypatch something like class ::String; def foo; end end. And second, load doesn't return the module it wraps the code into, so you basically have to fish it out of ObjectSpace::each_object(Module) by hand.
I was running a Rails application and in Gemfile, I had a specific custom gem I created with the option "require: false". Now when I loaded up rails server or rails console, I was able to require the gem in the initializer and the gem was loaded. However, when I ran a spec feature test with rspec and capybara, I got a load error. And I was completely bewildered why the Gem was not found in $LOAD_PATH when running a test.
So I reviewed all the different ways that load, require, rubygems and bundler interact. And these are a summary of my findings that helped me discover the solution to my particular problem:
load
1) You can pass it an absolute path to a ruby file and it will execute the code in that file.
load('/Users/myuser/foo.rb')
2) You can pass a relative path to load. If you are in same directory as file, it will find it:
> load('./foo.rb')
foo.rb loaded!
=> true
But if you try to load a file from different directory with load(), it will not find it with a relative path based on current working directory (e.g. ./):
> load('./foo.rb')
LoadError: cannot load such file -- foo.rb
3) As shown above, load always returns true (if the file could not be loaded it raises a LoadError).
4) Global variables, classes, constants and methods are all imported, but not local variables.
5) Calling load twice on the same file will execute the code in that file twice. If the specified file defines a constant, it will define that constant twice, which produces a warning.
6) $LOAD_PATH is an array of absolute paths. If you pass load just a file name, it will loop through $LOAD_PATH and search for the file in each directory.
> $LOAD_PATH.push("/Users/myuser")
> load('foo.rb')
foo.rb loaded!
=> true
require
1) Calling require on the same file twice will only execute it once. It’s also smart enough not to load the same file twice if you refer to it once with a relative path and once with an absolute path.
2) require returns true if the file was executed and false if it wasn’t.
3) require keeps track of which files have been loaded already in the global variable $LOADED_FEATURES.
4) You don’t need to include the file extension:
require 'foo'
5) require will look for foo.rb, but also dynamic library files, like foo.so, foo.o, or foo.dll. This is how you can call C code from ruby.
6) require does not check the current directory, since the current directory is by default not in $LOAD_PATH.
7) require_relative takes a path relative to the current file, not the working directory of the process.
Rubygems
1) Rubygems is a package manager designed to easily manage the installation of Ruby libraries called gems.
2) It packages its content as a zip file containing a bunch of ruby files and/or dynamic library files that can be imported by your code, along with some metadata.
3) Rubygems replaces the default require method with its own version. That version will look through your installed gems in addition to the directories in $LOAD_PATH. If Rubygems finds the file in your gems, it will add that gem to your $LOAD_PATH.
4) The gem install command figures out all of the dependencies of a gem and installs them. In fact, it installs all of a gem’s dependencies before it installs the gem itself.
Bundler
1) Bundler lets you specify all the gems your project needs, and optionally what versions of those gems. Then the bundle command installs all those gems and their dependencies.
2) You specify which gems you need in a file called Gemfile.
3) The bundle command also installs all the gems listed in Gemfile.lock at the specific versions listed.
4) Putting bundle exec before a command, e.g. bundle exec rspec, ensures that require will load the version of a gem specified in your Gemfile.lock.
Rails and Bundler
1) In config/boot.rb, require 'bundler/setup' is run. Bundler makes sure that Ruby can find all of the gems in the Gemfile (and all of their dependencies). require 'bundler/setup' will automatically discover your Gemfile, and make all of the gems in your Gemfile available to Ruby (in technical terms, it puts the gems “on the load path”). You can think of it as an adding some extra powers to require 'rubygems'.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
2) Now that your code is available to Ruby, you can require the gems that you need. For instance, you can require 'sinatra'. If you have a lot of dependencies, you might want to say “require all of the gems in my Gemfile”. To do this, put the following code immediately following require 'bundler/setup':
Bundler.require(:default)
3) By default, calling Bundler.require will require each gem in your Gemfile. If the line in the Gemfile says gem 'foo', :require => false then it will make sure foo is installed, but it won’t call require. You’ll have to call require('foo') if you want to use the gem.
So given this breadth of knowledge, I returned to the issue of my test and realized I had to explicitly require the gem in rails_helper.rb, since Bundler.setup added it to $LOAD_PATH but require: false precluded Bundler.require from requiring it explicitly. And then the issue was resolved.

Where are required gems defined?

In my rails application I once used authlogic-oid and ruby-openid. Now I want to get rid of them and I removed both gems and also their config.gem lines from my environment.rb.
Although my application works, I can't do any database migrations because I get a "Missing these required gems" error. Also if I run rake gems:install these gems are re-installed.
Where are the references to the gems stored?
The standard way to define a gem dependency is in the environment configuration. It usually takes place in the environment.rb file for any environment, but some gems might be specified also per-environment. Check the environment files in config/environments.
Also make sure some file doesn't include the gem with the classic RubyGems gem command.
Finally, check these gems are not required by other gems or plugins used by your application.

Resources