Ambiguity in Ruby class name resolution
I recently did some code refactoring in a Rails codebase in which I converted some code that defined some classes like this (class bodies elided):
foo/user_bar.rb:
module Foo
class UserBar; end
end
foo/sub_user_bar.rb:
module Foo
class SubUserBar < UserBar; end
end
...to:
In foo/bar/user.rb:
module Foo
module Bar
class User; end
end
end
In foo/bar/sub_user.rb:
module Foo
module Bar
class SubUser < User; end
end
end
This introduced a subtle problem in that there was already an existing top-level class called User (a Rails model), and SubUser was being derived from that, not from User in the same module. I'm guess that this is because the order that Rails loads classes is unpredictable...?
Anyway, I found that I could disambiguate by declaring the SubUser class like this:
class SubUser < self::User
...which seems to work, although I couldn't find any examples of it in a modest amount of searching. It does look a little weird, though. And now I'm concerned that I really ought to be doing this for every class in my module, just in case a top-level class with the same name is ever introduced.
There are two styles of in-module class declarations throughout my company's codebase:
class A::B::Foo; end
And:
module A; module B; class Foo; end; end; end
I've always preferred the latter method since it allows for access to other names in the module without fully-qualified names, but now I've found that there's potentially a trap when I use it. So what's the best practice here?
- Don't declare classes within a
module; always use fully qualified names (class A::B::C::Foo < A::B::C::Bar) - Declare classes in a
modulebut always fully qualify superclass names (module A; module B; module C; class Foo < A::B::C::Bar) - Declare classes in a
moduleand use unqualified names but always useself::when extending a class in the same module - Declare classes in a
moduleand use unqualified names but stay aware of possible name collisions in the top-level namespace (seems risky)
Or do Ruby and/or Rails offer some other, cleaner way to resolve the issue?
ruby-on-rails ruby
add a comment |
I recently did some code refactoring in a Rails codebase in which I converted some code that defined some classes like this (class bodies elided):
foo/user_bar.rb:
module Foo
class UserBar; end
end
foo/sub_user_bar.rb:
module Foo
class SubUserBar < UserBar; end
end
...to:
In foo/bar/user.rb:
module Foo
module Bar
class User; end
end
end
In foo/bar/sub_user.rb:
module Foo
module Bar
class SubUser < User; end
end
end
This introduced a subtle problem in that there was already an existing top-level class called User (a Rails model), and SubUser was being derived from that, not from User in the same module. I'm guess that this is because the order that Rails loads classes is unpredictable...?
Anyway, I found that I could disambiguate by declaring the SubUser class like this:
class SubUser < self::User
...which seems to work, although I couldn't find any examples of it in a modest amount of searching. It does look a little weird, though. And now I'm concerned that I really ought to be doing this for every class in my module, just in case a top-level class with the same name is ever introduced.
There are two styles of in-module class declarations throughout my company's codebase:
class A::B::Foo; end
And:
module A; module B; class Foo; end; end; end
I've always preferred the latter method since it allows for access to other names in the module without fully-qualified names, but now I've found that there's potentially a trap when I use it. So what's the best practice here?
- Don't declare classes within a
module; always use fully qualified names (class A::B::C::Foo < A::B::C::Bar) - Declare classes in a
modulebut always fully qualify superclass names (module A; module B; module C; class Foo < A::B::C::Bar) - Declare classes in a
moduleand use unqualified names but always useself::when extending a class in the same module - Declare classes in a
moduleand use unqualified names but stay aware of possible name collisions in the top-level namespace (seems risky)
Or do Ruby and/or Rails offer some other, cleaner way to resolve the issue?
ruby-on-rails ruby
add a comment |
I recently did some code refactoring in a Rails codebase in which I converted some code that defined some classes like this (class bodies elided):
foo/user_bar.rb:
module Foo
class UserBar; end
end
foo/sub_user_bar.rb:
module Foo
class SubUserBar < UserBar; end
end
...to:
In foo/bar/user.rb:
module Foo
module Bar
class User; end
end
end
In foo/bar/sub_user.rb:
module Foo
module Bar
class SubUser < User; end
end
end
This introduced a subtle problem in that there was already an existing top-level class called User (a Rails model), and SubUser was being derived from that, not from User in the same module. I'm guess that this is because the order that Rails loads classes is unpredictable...?
Anyway, I found that I could disambiguate by declaring the SubUser class like this:
class SubUser < self::User
...which seems to work, although I couldn't find any examples of it in a modest amount of searching. It does look a little weird, though. And now I'm concerned that I really ought to be doing this for every class in my module, just in case a top-level class with the same name is ever introduced.
There are two styles of in-module class declarations throughout my company's codebase:
class A::B::Foo; end
And:
module A; module B; class Foo; end; end; end
I've always preferred the latter method since it allows for access to other names in the module without fully-qualified names, but now I've found that there's potentially a trap when I use it. So what's the best practice here?
- Don't declare classes within a
module; always use fully qualified names (class A::B::C::Foo < A::B::C::Bar) - Declare classes in a
modulebut always fully qualify superclass names (module A; module B; module C; class Foo < A::B::C::Bar) - Declare classes in a
moduleand use unqualified names but always useself::when extending a class in the same module - Declare classes in a
moduleand use unqualified names but stay aware of possible name collisions in the top-level namespace (seems risky)
Or do Ruby and/or Rails offer some other, cleaner way to resolve the issue?
ruby-on-rails ruby
I recently did some code refactoring in a Rails codebase in which I converted some code that defined some classes like this (class bodies elided):
foo/user_bar.rb:
module Foo
class UserBar; end
end
foo/sub_user_bar.rb:
module Foo
class SubUserBar < UserBar; end
end
...to:
In foo/bar/user.rb:
module Foo
module Bar
class User; end
end
end
In foo/bar/sub_user.rb:
module Foo
module Bar
class SubUser < User; end
end
end
This introduced a subtle problem in that there was already an existing top-level class called User (a Rails model), and SubUser was being derived from that, not from User in the same module. I'm guess that this is because the order that Rails loads classes is unpredictable...?
Anyway, I found that I could disambiguate by declaring the SubUser class like this:
class SubUser < self::User
...which seems to work, although I couldn't find any examples of it in a modest amount of searching. It does look a little weird, though. And now I'm concerned that I really ought to be doing this for every class in my module, just in case a top-level class with the same name is ever introduced.
There are two styles of in-module class declarations throughout my company's codebase:
class A::B::Foo; end
And:
module A; module B; class Foo; end; end; end
I've always preferred the latter method since it allows for access to other names in the module without fully-qualified names, but now I've found that there's potentially a trap when I use it. So what's the best practice here?
- Don't declare classes within a
module; always use fully qualified names (class A::B::C::Foo < A::B::C::Bar) - Declare classes in a
modulebut always fully qualify superclass names (module A; module B; module C; class Foo < A::B::C::Bar) - Declare classes in a
moduleand use unqualified names but always useself::when extending a class in the same module - Declare classes in a
moduleand use unqualified names but stay aware of possible name collisions in the top-level namespace (seems risky)
Or do Ruby and/or Rails offer some other, cleaner way to resolve the issue?
ruby-on-rails ruby
ruby-on-rails ruby
asked Jan 18 at 20:04
SeanSean
23.4k36588
23.4k36588
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
Generally where there's ambiguity you specify full namespace paths:
module Foo
module Bar
class SubUser < Foo::Bar::User; end
end
end
That might seem verbose, but it's also specific and unambiguous.
Where you want to refer to literal top-level User you'd specify ::User.
add a comment |
Modules are identified by constants.1 The resolution of module look-ups is therefore determined by the procedure for looking up constant references. According to "The Ruby Programming Language", by David Flanagan and Yukihero Matsumoto, 1st Ed. 2008 (p. 261-262), constant look-ups are performed in the following order, where mod is the innermost module that encloses the reference to the constant:
mod.- the next enclosing module, continuing until there are no more enclosing modules. (Top-level/global constants are not considered at this step). The class method Module::nesting returns an array of modules that are so searched, in the order in which they are searched.
- the elements of
mod.ancestors, in index order (i.e., the inheritance hierarchy). - top-level constant definitions.
- the value returned by the method Module#const_missing, with
modbeing the receiver and the constant expressed as a symbol being the argument, provided the method has been defined.
Let's see what we may learn by inserting puts Module.nesting.inspect and puts ancestors statements into the code.
module Foo
class UserBar
puts "nesting for UserBar=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
# nesting for UserBar=[Foo::UserBar, Foo]
# Foo::UserBar.ancestors=[Foo::UserBar, Object, Kernel,
# BasicObject]
module Foo
class SubUserBar < UserBar
puts "nesting for SubUserBar=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
# nesting for SubUserBar=[Foo::SubUserBar, Foo]
# Foo::SubUserBar.ancestors=[Foo::SubUserBar,
# Foo::UserBar, Object, Kernel, BasicObject]
module Foo
module Bar
class User
puts "nesting for User=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
end
# nesting for User=[Foo::Bar::User, Foo::Bar, Foo]
# Foo::Bar::User.ancestors=[Foo::Bar::User, Object, Kernel,
# BasicObject]
module Foo
module Bar
class SubUser < User
puts "nesting for SubBar=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
end
# nesting for SubBar=[Foo::Bar::SubUser, Foo::Bar, Foo]
# Foo::Bar::SubUser.ancestors=[Foo::Bar::SubUser,
# Foo::Bar::User, Object, Kernel, BasicObject]
This tells us that if there is a class User that is not contained within Foo (as in Rails), that class would the subject of references to User in the classes Foo::UserBar and Foo::SubUserBar, but not in Foo::Bar::User or Foo::Bar::SubUser. This understanding should help in organising modules to avoid namespace problems.
1 As classes are modules, whenever I reference "module" below I am referring to classes as well as modules that are not classes.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54260744%2fambiguity-in-ruby-class-name-resolution%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Generally where there's ambiguity you specify full namespace paths:
module Foo
module Bar
class SubUser < Foo::Bar::User; end
end
end
That might seem verbose, but it's also specific and unambiguous.
Where you want to refer to literal top-level User you'd specify ::User.
add a comment |
Generally where there's ambiguity you specify full namespace paths:
module Foo
module Bar
class SubUser < Foo::Bar::User; end
end
end
That might seem verbose, but it's also specific and unambiguous.
Where you want to refer to literal top-level User you'd specify ::User.
add a comment |
Generally where there's ambiguity you specify full namespace paths:
module Foo
module Bar
class SubUser < Foo::Bar::User; end
end
end
That might seem verbose, but it's also specific and unambiguous.
Where you want to refer to literal top-level User you'd specify ::User.
Generally where there's ambiguity you specify full namespace paths:
module Foo
module Bar
class SubUser < Foo::Bar::User; end
end
end
That might seem verbose, but it's also specific and unambiguous.
Where you want to refer to literal top-level User you'd specify ::User.
answered Jan 18 at 20:48
tadmantadman
153k18174208
153k18174208
add a comment |
add a comment |
Modules are identified by constants.1 The resolution of module look-ups is therefore determined by the procedure for looking up constant references. According to "The Ruby Programming Language", by David Flanagan and Yukihero Matsumoto, 1st Ed. 2008 (p. 261-262), constant look-ups are performed in the following order, where mod is the innermost module that encloses the reference to the constant:
mod.- the next enclosing module, continuing until there are no more enclosing modules. (Top-level/global constants are not considered at this step). The class method Module::nesting returns an array of modules that are so searched, in the order in which they are searched.
- the elements of
mod.ancestors, in index order (i.e., the inheritance hierarchy). - top-level constant definitions.
- the value returned by the method Module#const_missing, with
modbeing the receiver and the constant expressed as a symbol being the argument, provided the method has been defined.
Let's see what we may learn by inserting puts Module.nesting.inspect and puts ancestors statements into the code.
module Foo
class UserBar
puts "nesting for UserBar=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
# nesting for UserBar=[Foo::UserBar, Foo]
# Foo::UserBar.ancestors=[Foo::UserBar, Object, Kernel,
# BasicObject]
module Foo
class SubUserBar < UserBar
puts "nesting for SubUserBar=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
# nesting for SubUserBar=[Foo::SubUserBar, Foo]
# Foo::SubUserBar.ancestors=[Foo::SubUserBar,
# Foo::UserBar, Object, Kernel, BasicObject]
module Foo
module Bar
class User
puts "nesting for User=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
end
# nesting for User=[Foo::Bar::User, Foo::Bar, Foo]
# Foo::Bar::User.ancestors=[Foo::Bar::User, Object, Kernel,
# BasicObject]
module Foo
module Bar
class SubUser < User
puts "nesting for SubBar=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
end
# nesting for SubBar=[Foo::Bar::SubUser, Foo::Bar, Foo]
# Foo::Bar::SubUser.ancestors=[Foo::Bar::SubUser,
# Foo::Bar::User, Object, Kernel, BasicObject]
This tells us that if there is a class User that is not contained within Foo (as in Rails), that class would the subject of references to User in the classes Foo::UserBar and Foo::SubUserBar, but not in Foo::Bar::User or Foo::Bar::SubUser. This understanding should help in organising modules to avoid namespace problems.
1 As classes are modules, whenever I reference "module" below I am referring to classes as well as modules that are not classes.
add a comment |
Modules are identified by constants.1 The resolution of module look-ups is therefore determined by the procedure for looking up constant references. According to "The Ruby Programming Language", by David Flanagan and Yukihero Matsumoto, 1st Ed. 2008 (p. 261-262), constant look-ups are performed in the following order, where mod is the innermost module that encloses the reference to the constant:
mod.- the next enclosing module, continuing until there are no more enclosing modules. (Top-level/global constants are not considered at this step). The class method Module::nesting returns an array of modules that are so searched, in the order in which they are searched.
- the elements of
mod.ancestors, in index order (i.e., the inheritance hierarchy). - top-level constant definitions.
- the value returned by the method Module#const_missing, with
modbeing the receiver and the constant expressed as a symbol being the argument, provided the method has been defined.
Let's see what we may learn by inserting puts Module.nesting.inspect and puts ancestors statements into the code.
module Foo
class UserBar
puts "nesting for UserBar=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
# nesting for UserBar=[Foo::UserBar, Foo]
# Foo::UserBar.ancestors=[Foo::UserBar, Object, Kernel,
# BasicObject]
module Foo
class SubUserBar < UserBar
puts "nesting for SubUserBar=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
# nesting for SubUserBar=[Foo::SubUserBar, Foo]
# Foo::SubUserBar.ancestors=[Foo::SubUserBar,
# Foo::UserBar, Object, Kernel, BasicObject]
module Foo
module Bar
class User
puts "nesting for User=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
end
# nesting for User=[Foo::Bar::User, Foo::Bar, Foo]
# Foo::Bar::User.ancestors=[Foo::Bar::User, Object, Kernel,
# BasicObject]
module Foo
module Bar
class SubUser < User
puts "nesting for SubBar=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
end
# nesting for SubBar=[Foo::Bar::SubUser, Foo::Bar, Foo]
# Foo::Bar::SubUser.ancestors=[Foo::Bar::SubUser,
# Foo::Bar::User, Object, Kernel, BasicObject]
This tells us that if there is a class User that is not contained within Foo (as in Rails), that class would the subject of references to User in the classes Foo::UserBar and Foo::SubUserBar, but not in Foo::Bar::User or Foo::Bar::SubUser. This understanding should help in organising modules to avoid namespace problems.
1 As classes are modules, whenever I reference "module" below I am referring to classes as well as modules that are not classes.
add a comment |
Modules are identified by constants.1 The resolution of module look-ups is therefore determined by the procedure for looking up constant references. According to "The Ruby Programming Language", by David Flanagan and Yukihero Matsumoto, 1st Ed. 2008 (p. 261-262), constant look-ups are performed in the following order, where mod is the innermost module that encloses the reference to the constant:
mod.- the next enclosing module, continuing until there are no more enclosing modules. (Top-level/global constants are not considered at this step). The class method Module::nesting returns an array of modules that are so searched, in the order in which they are searched.
- the elements of
mod.ancestors, in index order (i.e., the inheritance hierarchy). - top-level constant definitions.
- the value returned by the method Module#const_missing, with
modbeing the receiver and the constant expressed as a symbol being the argument, provided the method has been defined.
Let's see what we may learn by inserting puts Module.nesting.inspect and puts ancestors statements into the code.
module Foo
class UserBar
puts "nesting for UserBar=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
# nesting for UserBar=[Foo::UserBar, Foo]
# Foo::UserBar.ancestors=[Foo::UserBar, Object, Kernel,
# BasicObject]
module Foo
class SubUserBar < UserBar
puts "nesting for SubUserBar=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
# nesting for SubUserBar=[Foo::SubUserBar, Foo]
# Foo::SubUserBar.ancestors=[Foo::SubUserBar,
# Foo::UserBar, Object, Kernel, BasicObject]
module Foo
module Bar
class User
puts "nesting for User=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
end
# nesting for User=[Foo::Bar::User, Foo::Bar, Foo]
# Foo::Bar::User.ancestors=[Foo::Bar::User, Object, Kernel,
# BasicObject]
module Foo
module Bar
class SubUser < User
puts "nesting for SubBar=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
end
# nesting for SubBar=[Foo::Bar::SubUser, Foo::Bar, Foo]
# Foo::Bar::SubUser.ancestors=[Foo::Bar::SubUser,
# Foo::Bar::User, Object, Kernel, BasicObject]
This tells us that if there is a class User that is not contained within Foo (as in Rails), that class would the subject of references to User in the classes Foo::UserBar and Foo::SubUserBar, but not in Foo::Bar::User or Foo::Bar::SubUser. This understanding should help in organising modules to avoid namespace problems.
1 As classes are modules, whenever I reference "module" below I am referring to classes as well as modules that are not classes.
Modules are identified by constants.1 The resolution of module look-ups is therefore determined by the procedure for looking up constant references. According to "The Ruby Programming Language", by David Flanagan and Yukihero Matsumoto, 1st Ed. 2008 (p. 261-262), constant look-ups are performed in the following order, where mod is the innermost module that encloses the reference to the constant:
mod.- the next enclosing module, continuing until there are no more enclosing modules. (Top-level/global constants are not considered at this step). The class method Module::nesting returns an array of modules that are so searched, in the order in which they are searched.
- the elements of
mod.ancestors, in index order (i.e., the inheritance hierarchy). - top-level constant definitions.
- the value returned by the method Module#const_missing, with
modbeing the receiver and the constant expressed as a symbol being the argument, provided the method has been defined.
Let's see what we may learn by inserting puts Module.nesting.inspect and puts ancestors statements into the code.
module Foo
class UserBar
puts "nesting for UserBar=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
# nesting for UserBar=[Foo::UserBar, Foo]
# Foo::UserBar.ancestors=[Foo::UserBar, Object, Kernel,
# BasicObject]
module Foo
class SubUserBar < UserBar
puts "nesting for SubUserBar=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
# nesting for SubUserBar=[Foo::SubUserBar, Foo]
# Foo::SubUserBar.ancestors=[Foo::SubUserBar,
# Foo::UserBar, Object, Kernel, BasicObject]
module Foo
module Bar
class User
puts "nesting for User=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
end
# nesting for User=[Foo::Bar::User, Foo::Bar, Foo]
# Foo::Bar::User.ancestors=[Foo::Bar::User, Object, Kernel,
# BasicObject]
module Foo
module Bar
class SubUser < User
puts "nesting for SubBar=#{Module.nesting.inspect}"
puts "#{self}.ancestors=#{ancestors}"
end
end
end
# nesting for SubBar=[Foo::Bar::SubUser, Foo::Bar, Foo]
# Foo::Bar::SubUser.ancestors=[Foo::Bar::SubUser,
# Foo::Bar::User, Object, Kernel, BasicObject]
This tells us that if there is a class User that is not contained within Foo (as in Rails), that class would the subject of references to User in the classes Foo::UserBar and Foo::SubUserBar, but not in Foo::Bar::User or Foo::Bar::SubUser. This understanding should help in organising modules to avoid namespace problems.
1 As classes are modules, whenever I reference "module" below I am referring to classes as well as modules that are not classes.
edited Jan 18 at 22:39
answered Jan 18 at 22:33
Cary SwovelandCary Swoveland
68.7k54065
68.7k54065
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54260744%2fambiguity-in-ruby-class-name-resolution%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown