Project

General

Profile

Actions

Feature #5690

closed

Module#qualified_const_get

Added by wycats (Yehuda Katz) about 13 years ago. Updated over 8 years ago.

Status:
Closed
Target version:
-
[ruby-core:41404]

Description

It would be great if there was a way to dynamically load a constant path:

module Foo
  module Bar
    module Baz
    end
  end
end

Foo.qualified_const_get("Bar::Baz") => Foo::Bar::Baz

Files

noname (500 Bytes) noname Anonymous, 12/01/2011 10:23 AM
bug5690.pdf (615 KB) bug5690.pdf tenderlovemaking (Aaron Patterson), 07/01/2012 01:29 AM
noname (500 Bytes) noname Anonymous, 07/02/2012 11:53 PM
p2c.diff (4.86 KB) p2c.diff tenderlovemaking (Aaron Patterson), 10/24/2012 02:40 AM

Related issues 3 (1 open2 closed)

Related to Ruby master - Feature #5666: Make rb_path2class publicClosedtenderlovemaking (Aaron Patterson)11/24/2011Actions
Related to Ruby master - Feature #12319: `Module#const_get` does not accept symbol with nested nameOpenActions
Has duplicate Ruby master - Feature #767: Module#const_getでネストした定数の値を得られてもよいと思うRejectedmatz (Yukihiro Matsumoto)11/21/2008Actions
Actions #1

Updated by naruse (Yui NARUSE) about 13 years ago

  • Category set to core
  • Status changed from Open to Assigned
  • Assignee set to matz (Yukihiro Matsumoto)
  • Target version set to 2.0.0

Updated by matz (Yukihiro Matsumoto) about 13 years ago

  • ruby -v changed from ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-darwin11.2.0] to -

Hi,

In message "Re: [ruby-core:41404] [ruby-trunk - Bug #5690][Open] Module#qualified_const_get"
on Wed, 30 Nov 2011 12:10:02 +0900, Yehuda Katz writes:

It would be great if there was a way to dynamically load a constant path:

module Foo
  module Bar
    module Baz
    end
  end
end

Foo.qualified_const_get("Bar::Baz") => Foo::Bar::Baz

Interesting.

  • is there any use-case for this method?

  • if Bar is not a class nor module, what kind error should be raised?

  • is qualified_const_get an appropriate name for the function?

      					matz.
    

Updated by matz (Yukihiro Matsumoto) about 13 years ago

Hi,

In message "Re: [ruby-core:41408] Re: [ruby-trunk - Bug #5690][Open] Module#qualified_const_get"
on Wed, 30 Nov 2011 16:52:36 +0900, Yehuda Katz writes:

  • is there any use-case for this method?

We use it often in Rails.

Could you show us the concrete example? It is difficult for me to
imagine.

  • if Bar is not a class nor module, what kind error should be raised?

TypeError: "(…) is not a class/module"

Understood.

  • is qualified_const_get an appropriate name for the function?

Unknown. It's what we call it in Rails ;)

How about

Foo.const_get("Bar::Baz")

or

Foo.const_get(:Bar, :Baz)

?

						matz.

Updated by wycats (Yehuda Katz) about 13 years ago

Yehuda Katz
(ph) 718.877.1325

2011/11/30 Yukihiro Matsumoto

Hi,

In message "Re: [ruby-core:41408] Re: [ruby-trunk - Bug #5690][Open]
Module#qualified_const_get"
on Wed, 30 Nov 2011 16:52:36 +0900, Yehuda Katz
writes:

|> * is there any use-case for this method?
|
|We use it often in Rails.

Could you show us the concrete example? It is difficult for me to
imagine.

One case is to convert path names (file system paths) into constants.

In general, Rails uses inflections to convert names from different
contexts. In the router, for instance, "foo/bar" is used to represent
namespaces, which are then converted into "Foo::Bar" and then Foo::Bar.

|> * if Bar is not a class nor module, what kind error should be raised?
|>
|
|TypeError: "(…) is not a class/module"

Understood.

|> * is qualified_const_get an appropriate name for the function?
|>
|
|Unknown. It's what we call it in Rails ;)

How about

Foo.const_get("Bar::Baz")

Sounds good to me. Currently, trying to const_set or const_get a name with
:: in it produces a NameError, so it should not introduces new issues.

or

Foo.const_get(:Bar, :Baz)

This doesn't satisfy the use-case in question.

?

                                                   matz.

Updated by Anonymous about 13 years ago

On Wed, Nov 30, 2011 at 04:52:36PM +0900, Yehuda Katz wrote:

On Tue, Nov 29, 2011 at 10:04 PM, Yukihiro Matsumoto wrote:

Hi,

In message "Re: [ruby-core:41404] [ruby-trunk - Bug #5690][Open]
Module#qualified_const_get"
on Wed, 30 Nov 2011 12:10:02 +0900, Yehuda Katz
writes:

|It would be great if there was a way to dynamically load a constant path:
|
| module Foo
| module Bar
| module Baz
| end
| end
| end
|
| Foo.qualified_const_get("Bar::Baz") => Foo::Bar::Baz

Interesting.

  • is there any use-case for this method?

We use it often in Rails.

When serializing objects to yaml, the fully qualified class name is
emitted. When reviving those objects, the class name comes back as a
string, so psych uses rb_path2class to find the constant.

  • if Bar is not a class nor module, what kind error should be raised?

TypeError: "(…) is not a class/module"

Agreed.

  • is qualified_const_get an appropriate name for the function?
    Unknown. It's what we call it in Rails ;)

Yes.

--
Aaron Patterson
http://tenderlovemaking.com/

Updated by naruse (Yui NARUSE) almost 13 years ago

(2011/12/01 5:59), Yehuda Katz wrote:

Yehuda Katz
(ph) 718.877.1325

2011/11/30 Yukihiro Matsumoto < >

Hi,

In message "Re: [ruby-core:41408] Re: [ruby-trunk - Bug #5690][Open] Module#qualified_const_get"
   on Wed, 30 Nov 2011 16:52:36 +0900, Yehuda Katz <wycats@gmail.com <mailto:wycats@gmail.com>> writes:

|> * is there any use-case for this method?
|
|We use it often in Rails.

Could you show us the concrete example?  It is difficult for me to
imagine.

One case is to convert path names (file system paths) into constants.

In general, Rails uses inflections to convert names from different contexts. In the router, for instance, "foo/bar" is used to represent namespaces, which are then converted into "Foo::Bar" and then Foo::Bar.

"concrete exapmle" needs "what is the router?" and "when the router is used?".

--
NARUSE, Yui

Updated by ko1 (Koichi Sasada) almost 13 years ago

(2011/11/30 12:10), Yehuda Katz wrote:

It would be great if there was a way to dynamically load a constant path:

module Foo
  module Bar
    module Baz
    end
  end
end

Foo.qualified_const_get("Bar::Baz") => Foo::Bar::Baz

Any progress on it?

There are several similar proposals.
I think 2.0 is a good opportunity to finish such discussion.

BTW, is it a "BUG"? (on title)

--
// SASADA Koichi at atdot dot net

Updated by trans (Thomas Sawyer) almost 13 years ago

Please, can we avoid the use such abstract name.

Is the speed hit too great that Ruby's can't just use #const_get for this as well? I suspect the Rail's method name was chosen simply to avoid a monkey patch.

Of course, in Facets the method is just called #constant. Heaven forbid we use the obvious name ;-)

Updated by fxn (Xavier Noria) almost 13 years ago

I wrote qualified_const_get in Active Support. The rationale for that name was: 1) I didn't want to touch const_get. const_get is supposed to raise an exception if the argument is not a valid constant name and "Foo::Bar" is not a valid constant name. I didn't want to change that expectation in such a fundamental method. And 2) I wanted a name that was obvious. Given that a Ruby programmer knows const_get, he will instantly know what qualified_const_get is going to do. In that sense I don't think this method is more abstract than const_get, it is in my view rather the natural companion of const_get.

That's for the current name. If this was going to be considered for Ruby 2.0 I think I'd prefer this behavior to be available in const_get itself.

Updated by trans (Thomas Sawyer) almost 13 years ago

I don't think the name is particularly obvious. Nevertheless, I am hopeful that it won't matter. I think const_get can accommodate. In fact, I think it can even be made to handle:

const_get('Foo', 'Bar::Baz') #=> Foo::Bar::Baz

It is backward compatible, after all.

Updated by trans (Thomas Sawyer) almost 13 years ago

@Xavier Let me "qualify" that ;-) I think your reasoning made very good sense for adding to ActiveSupport. But becoming part of Ruby, there is the opportunity to do it "right", as your last statement concurs.

Updated by marcandre (Marc-Andre Lafortune) over 12 years ago

Is anyone producing a slide-show for this?

Updated by tenderlovemaking (Aaron Patterson) over 12 years ago

  • File bug5690.pdf added

Adding a slide for this feature.

Actions #14

Updated by tenderlovemaking (Aaron Patterson) over 12 years ago

  • File deleted (bug5690.pdf)

Updated by marcandre (Marc-Andre Lafortune) over 12 years ago

Cool slide :-)

+1 from me, but modifying existing const_get. No incompatibility as "Foo::Bar" are currently invalid constant names. And const_set should be modified as well (raises a Name if the path up to the last constant name does not exist or is not a Module/Class).

Updated by trans (Thomas Sawyer) over 12 years ago

I agree with marcandre. Why bother with an additional (and long named) method, when current method can suffice?

Updated by mame (Yusuke Endoh) over 12 years ago

Aaron, your slide is received. Thank you.

marcandre (Marc-Andre Lafortune) wrote:

+1 from me, but modifying existing const_get.

I'll add it verbally during the presentation, if I recall.

--
Yusuke Endoh

Updated by Anonymous over 12 years ago

On Mon, Jul 02, 2012 at 01:54:32AM +0900, mame (Yusuke Endoh) wrote:

Issue #5690 has been updated by mame (Yusuke Endoh).

Aaron, your slide is received. Thank you.

marcandre (Marc-Andre Lafortune) wrote:

+1 from me, but modifying existing const_get.

I'll add it verbally during the presentation, if I recall.

Thank you!

--
Aaron Patterson
http://tenderlovemaking.com/

Updated by ko1 (Koichi Sasada) over 12 years ago

  • Tracker changed from Bug to Feature

Updated by mame (Yusuke Endoh) over 12 years ago

  • Assignee changed from matz (Yukihiro Matsumoto) to tenderlovemaking (Aaron Patterson)

Yehuda Katz and Aaron Patterson,

I'm happy to inform you that matz has accepted your proposal,
as one to extend existing const_get' (not qualified_const_get').

Aaron, could you implement a patch?

--
Yusuke Endoh

Updated by cjheath (Clifford Heath) over 12 years ago

Aaron,

On 24/07/2012, at 4:14 AM, Aaron Patterson wrote:

On Mon, Jul 23, 2012 at 09:39:38PM +0900, mame (Yusuke Endoh) wrote:

Issue #5690 has been updated by mame (Yusuke Endoh).
Assignee changed from matz (Yukihiro Matsumoto) to tenderlovemaking (Aaron Patterson)
Yehuda Katz and Aaron Patterson,
I'm happy to inform you that matz has accepted your proposal,
as one to extend existing const_get' (not qualified_const_get').

Aaron, could you implement a patch?
Yes I will. Thanks! :-)

Please ensure that if the lookup fails, the exception indicates which part of the name caused the failure.

It's waaay past time that the industry moves past "ENOENT: No such file or directory" in its exception reporting :)

Thank-you.

Clifford Heath.

Updated by tenderlovemaking (Aaron Patterson) about 12 years ago

I've written a patch this this feature, and I've attached it here. Will someone review so that we can figure out what needs to change before it's applied? Thank you.

Updated by ko1 (Koichi Sasada) about 12 years ago

I got SEGV.
could you run "make test-rubyspec" on your environment?

/mnt/sdb1/ruby/trunk/spec/rubyspec/core/module/const_get_spec.rb:34: [BUG] Segmentation fault
ruby 2.0.0dev (2012-10-27 trunk 37336) [x86_64-linux]

-- Control frame information -----------------------------------------------
c:0031 p:---- s:0108 e:000107 CFUNC :const_get
c:0030 p:0038 s:0104 e:000103 BLOCK /mnt/sdb1/ruby/trunk/spec/rubyspec/core/module/const_get_spec.rb:34 [FINISH]
c:0029 p:---- s:0101 e:000100 CFUNC :instance_eval
c:0028 p:0014 s:0098 e:000097 METHOD /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:69
c:0027 p:0017 s:0092 e:000091 BLOCK /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/context.rb:179 [FINISH]
c:0026 p:---- s:0089 e:000088 IFUNC
c:0025 p:---- s:0087 e:000086 CFUNC :each
c:0024 p:---- s:0085 e:000084 CFUNC :all?
c:0023 p:0044 s:0082 e:000081 METHOD /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/context.rb:179
c:0022 p:0077 s:0076 e:000075 BLOCK /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/context.rb:208
c:0021 p:0004 s:0072 e:000071 BLOCK /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:239 [FINISH]
c:0020 p:---- s:0070 e:000069 CFUNC :times
c:0019 p:0017 s:0067 e:000066 METHOD /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:238
c:0018 p:0011 s:0064 e:000063 BLOCK /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/context.rb:200 [FINISH]
c:0017 p:---- s:0061 e:000060 CFUNC :each
c:0016 p:0091 s:0058 e:000057 METHOD /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/context.rb:199
c:0015 p:0087 s:0055 e:000054 METHOD /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:38
c:0014 p:0030 s:0048 e:000047 METHOD /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/object.rb:11
c:0013 p:0045 s:0041 e:000c28 TOP /mnt/sdb1/ruby/trunk/spec/rubyspec/core/module/const_get_spec.rb:4 [FINISH]
c:0012 p:---- s:0039 e:000038 CFUNC :load
c:0011 p:0014 s:0035 e:000034 BLOCK /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:57 [FINISH]
c:0010 p:---- s:0033 e:000032 CFUNC :instance_eval
c:0009 p:0014 s:0030 e:000029 METHOD /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:69
c:0008 p:0061 s:0024 e:0000e0 BLOCK /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:57 [FINISH]
c:0007 p:---- s:0021 e:000020 CFUNC :each
c:0006 p:0042 s:0018 e:001450 METHOD /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:51
c:0005 p:0015 s:0014 e:000013 METHOD /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:43
c:0004 p:0047 s:0011 e:000010 METHOD /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/commands/mspec-run.rb:91
c:0003 p:0077 s:0008 e:000007 METHOD /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/utils/script.rb:218
c:0002 p:0047 s:0004 e:000ac8 EVAL /mnt/sdb1/ruby/trunk/spec/mspec/bin/mspec-run:8 [FINISH]
c:0001 p:0000 s:0002 e:0007f8 TOP [FINISH]

/mnt/sdb1/ruby/trunk/spec/mspec/bin/mspec-run:8:in <main>' /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/utils/script.rb:218:in main'
/mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/commands/mspec-run.rb:91:in run' /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:43:in process'
/mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:51:in files' /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:51:in each'
/mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:57:in block in files' /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:69:in protect'
/mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:69:in instance_eval' /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:57:in block (2 levels) in files'
/mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:57:in load' /mnt/sdb1/ruby/trunk/spec/rubyspec/core/module/const_get_spec.rb:4:in <top (required)>'
/mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/object.rb:11:in describe' /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:38:in describe'
/mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/context.rb:199:in process' /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/context.rb:199:in each'
/mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/context.rb:200:in block in process' /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:238:in repeat'
/mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:238:in times' /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:239:in block in repeat'
/mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/context.rb:208:in block (2 levels) in process' /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/context.rb:179:in protect'
/mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/context.rb:179:in all?' /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/context.rb:179:in each'
/mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/context.rb:179:in block in protect' /mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:69:in protect'
/mnt/sdb1/ruby/trunk/spec/mspec/lib/mspec/runner/mspec.rb:69:in instance_eval' /mnt/sdb1/ruby/trunk/spec/rubyspec/core/module/const_get_spec.rb:34:in block (2 levels) in <top (required)>'
/mnt/sdb1/ruby/trunk/spec/rubyspec/core/module/const_get_spec.rb:34:in `const_get'

-- C level backtrace information -------------------------------------------
make: *** [test-rubyspec] セグメンテーション違反です

Updated by Anonymous about 12 years ago

On Sat, Oct 27, 2012 at 09:11:51AM +0900, ko1 (Koichi Sasada) wrote:

Issue #5690 has been updated by ko1 (Koichi Sasada).

I got SEGV.
could you run "make test-rubyspec" on your environment?

I can't seem to run make test-rubyspec in my environment. It always
does this:

[aaron@higgins ruby (trunk)]$ make test-rubyspec
./miniruby -I./lib -I. -I.ext/common ./tool/runruby.rb --extout=.ext -- --disable-gems ./spec/mspec/bin/mspec run -B ./spec/default.mspec
ruby 2.0.0dev (2012-10-27 trunk 37339) [x86_64-darwin12.2.0]
/Users/aaron/git/ruby/spec/mspec/lib/mspec/guards/guard.rb:156:in block in os?': uninitialized constant SpecGuard::Config (NameError) from /Users/aaron/git/ruby/spec/mspec/lib/mspec/guards/guard.rb:155:in each'
from /Users/aaron/git/ruby/spec/mspec/lib/mspec/guards/guard.rb:155:in any?' from /Users/aaron/git/ruby/spec/mspec/lib/mspec/guards/guard.rb:155:in os?'
from /Users/aaron/git/ruby/spec/mspec/lib/mspec/guards/platform.rb:22:in `block in match?'

I'm not sure why. Anyway, I can run mspec by hand, and this should be
fixed in r37340.

--
Aaron Patterson
http://tenderlovemaking.com/

Updated by tenderlovemaking (Aaron Patterson) about 12 years ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

I committed this in r37340 and r37335

Actions #27

Updated by nobu (Nobuyoshi Nakada) over 8 years ago

  • Related to Feature #12319: `Module#const_get` does not accept symbol with nested name added

Updated by nobu (Nobuyoshi Nakada) over 8 years ago

  • Description updated (diff)
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0