Issue #13847 has been updated by shevegen (Robert A. Heiler).


> Also, in this use case, it seems to be enough to use [..]

> require 'json', version: :default, into: :Bundler 

Matz will decided but I wanted to comment on what Hiroshi Shibata wrote.

Kernel require presently accepts no additional arguments:

  https://ruby-doc.org/core-2.4.1/Kernel.html#method-i-require

So I guess the proposal also means to extend Kernel#require if
I understood it correctly.

I may be wrong but I think that matz may wish to keep require 
simple.

I myself have, since some time, wanted to have some more useful
or powerful ways for ruby to handle add-ons in general stored
in different files. Some time ago I noticed that load() has 
a second argument (boolean - true or false), and if false then
the loaded file will not modify the namespace. So it will be
an anonymous module. That was quite interesting to me. There
are also some tricks to be able to access the module still
such as on:

  http://iceruby.blogspot.co.at/2014/07/or-how-to-get-anonymous-module-from.html

(In case the above link no longer works at some point in 
time, and you don't want to search via the wayback www archive,
I'll very briefly mention what they do:

They use catch/throw trick such as:

    throw :wrapper, Module.nesting.last

and catch the error that way 

    catch :wrapper do
      load File.expand_path('b.rb'), true

Which was an interesting idea.)

Anyway, to come back to Hiroshi Shibata, I actually agree with the
proposal, although I come from another direction (in general to have
more power and control about how to load up add-ons and external
code, so this is why I am in support of it).

In Gemfiles, please correct me if I am wrong but there are ways to
speciically load certain versions such as via:

    gem 'openssl', '2.0.4'

So in my opinion, I believe that it may make sense for require
to accept a Hash too.

This Hash could allow for additional parameters that would allow
us rubyists for more finer-grained control.

Hiroshi gave the example:

    require 'json', version: '2.0.2', into: :Bundler

Perhaps we could also re-define importable namespaces, a bit similar
as to load() but actually attaching onto the main namespace of the
current ruby gem.

For example, if I have a project called foobar, with module Foobar,
and I am including an external project called bla, that has a toplevel
module namespace called Bla, then I could perhaps say that the namespace
Bla never "exists" but instead becomes attached towards module Foobar
at once.

Syntax proposals:

  require 'bla', version: '2.0.2', attach_as_namespace :Foobar

or something like this. However, please do not get too distracted
by my suggestion above; it's just what I personally would like to
be able to have. It is not so important for me whether this is
part of require, or load, or some other way, I am more interested
in the functionality, since I needed it a few times already.

I do not want to make Hiroshi's proposal too complicated, so I
want to end that I agree with his proposal.

+1


----------------------------------------
Feature #13847: Gem activated problem for default gems
https://bugs.ruby-lang.org/issues/13847#change-66322

* Author: hsbt (Hiroshi SHIBATA)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 2.5
----------------------------------------
If you try to use some default gems with a fixed version using Bundler, there are cases where the current RubyGems/Bundler/Ruby specification can not be used with the version specified by the user.

For example

```
$ ruby -v
ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin17]
$ gem list | grep openssl
openssl (2.0.5, 2.0.4, default: 2.0.3)
```

In the environment such as ```require 'openssl'```, the version that is activated when openssl is searched with openssl is the version found first, ie 2.0.5.

```
$ ruby -ropenssl -e 'p OpenSSL::VERSION'
"2.0.5"
```

At this time, for example, suppose the user really wants to use openssl 2.0.4 and wrote the following Gemfile.

```
> cat Gemfile
# frozen_string_literal: true
source "https://rubygems.org"

gem 'openssl', '2.0.4'
```

Unfortunately, since rubygems has required openssl before the bundler runs it will result in an activated error like this:

```
> bundle exec ruby -ropenssl -e 'p OpenSSL::VERSION'
/path/to/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/lib/bundler/runtime.rb:317:in `check_for_activated_spec!': You have already activated openssl 2.0.5, but your Gemfile requires openssl 2.0.4. Prepending `bundle exec` to your command may solve this. (Gem::LoadError)
```

This problem can be avoided by bundling it as a vendoring library under bundler's repository if it is a default gem implemented with pure ruby.

Https://github.com/bundler/bundler/blob/master/lib/bundler/vendor/fileutils/lib/fileutils.rb

In the case of bundler, by separating the namespace as `Bundler::FileUtils`, even the version specified by the user is made available without conflict at the time of activate. However, this method can not be used with C extension library.

Since we want to use json/psych from the bundler team with rubygems/bundler to serialize data, we need about whether we can implement a way to avoid some kind of C extension on Ruby itself.

I discussed with @indirect who is maintainer of RubyGems/Bundler. We can resolve this problem like following feature of ruby.

```
require_for_bundler 'json', '2.0.2'
```

When we declared above `require_for_bundler`, We put a json-2.0.2 to placed in a namespace like `Bundler::JSON`. There were similar issues in the past as well.

https://bugs.ruby-lang.org/issues/10320

I think that the way of writing ```require 'json', version: '2.0.2', into: :Bundler``` which extended the method like this issue seems like that. Also, in this use case, it seems to be enough to use ```require 'json', version: :default, into: :Bundler``` which forces the use of default gem.

Matz, How do you think about this feature?



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>