Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delegation of to_s to source? #560

Closed
olivierlacan opened this issue Jul 7, 2013 · 6 comments · Fixed by #561
Closed

Delegation of to_s to source? #560

olivierlacan opened this issue Jul 7, 2013 · 6 comments · Fixed by #561

Comments

@olivierlacan
Copy link
Contributor

Curious why with delegate_all called at the top of a Decorator I get "#<UserDecorator:0x007fd78b9dbc40>" when calling to_s while to_param properly delegates to the User class' to_param.

Any idea?

@haines
Copy link
Contributor

haines commented Jul 7, 2013

Hi Olivier, thanks for reporting this. Basically, delegate_all uses method_missing, which means that any methods that are already defined on Object need to be explicitly delegated.

For ActiveModel compatibility, we needed to delegate to_param (here) but we haven't previously had a need to delegate to_s. However I don't see any reason not to... @steveklabnik, thoughts?

@steveklabnik
Copy link
Member

Yeah, seems fine.

@tovodeverett
Copy link
Contributor

Note that this makes debugging a lot more confusing since the most common way to distinguish between a decorator and its object is no longer useful.

Before this change, from a rails s session:

>> Guest.instance.decorate(context: {current_user: Guest.instance})
=> #<GuestDecorator:0x000000058c8430
 @context={:current_user=>#<Guest:0x000000058c9100>},
 @object=#<Guest:0x000000058c9100>>

After this change:

>> Guest.instance.decorate(context: {current_user: Guest.instance})
=> #<Guest:0x00000005321310>

Even calling inspect doesn't help:

>> Guest.instance.decorate(context: {current_user: Guest.instance}).inspect
=> "#<Guest:0x00000005321310>"

@haines
Copy link
Contributor

haines commented Jul 8, 2013

Turns out to be an unfortunate difference between Ruby 1.9 and 2.0 - it looks like the Object#inspect method was simplified considerably between 1.9.3 and 2.0.0.

On 2.0 I get the expected result:

decorator = UserDecorator.new(User.new)
decorator.to_s     #=> "#<User:0x03ca1a18>"
decorator.inspect  #=> "#<UserDecorator:0x03ca1978 @object=#<User:0x03ca1a18>, @context={}>"

A custom inspect method could solve this, or we could just revert the change.

@tovodeverett
Copy link
Contributor

It turns out that this is one of the "five notable incompatibilities" - from http://www.ruby-lang.org/en/news/2013/02/24/ruby-2-0-0-p0-is-released/, "Object#inspect does always return a string like #ClassName:0x… instead of delegating to #to_s. [#2152]". A whole thread is at http://bugs.ruby-lang.org/issues/show/2152.

I wonder if it's possible to grab a reference to the original #to_s before it gets overridden and then to point #inspect at that, but only on Ruby < 2.0.0.

@olivierlacan
Copy link
Contributor Author

@haines Thanks again for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants