This project is archived and is in readonly mode.

#5953 ✓stale
Dim

STI type not updatable

Reported by Dim | November 11th, 2010 @ 04:28 PM

Imagine you have the following scenario:

@@@ class Employer < ActiveRecord::Base end

class Manager < Employer
end

employer = Employer.find(1) # => #
manager = employer.becomes(Manager) # => #
manager.save! # => #
Employer.find(1) # => #


The problem is in Persistence#update (https://github.com/rails/rails/blob/920660b19c5419c6df1c234a84e7fec71b169544/activerecord/lib/active_record/persistence.rb#L252). It calls Base#unscoped which calls Base#relation where type_condition is automatically applied. The resulting SQL statement is therefore UPDATE employers SET .... WHERE employers.id = 1 AND employers.type = 'Manager' and although #save! doesn't throw an error the record is not actually updated.


A test case is attached.

Comments and changes to this ticket

  • Dim

    Dim November 11th, 2010 @ 04:31 PM

    Sorry about the previous formatting issues, here again:

    Imagine you have the following scenario:

    class Employer < ActiveRecord::Base
    end
    
    class Manager < Employer
    end
    
    employer = Employer.find(1)          # => #<Employer>
    manager  = employer.becomes(Manager) # => #<Manager>
    manager.save!                        # => #<Manager>
    Employer.find(1)                     # => #<Employer>
    

    The problem is in Persistence#update. It calls Base#unscoped which calls Base#relation where type_condition is automatically applied. The resulting SQL statement is therefore

    UPDATE employers SET .... WHERE employers.id = 1 AND employers.type = 'Manager'`
    

    and although #save! doesn't throw an error the record is not actually updated.

    A test case is attached.

  • Neeraj Singh

    Neeraj Singh November 11th, 2010 @ 04:52 PM

    • Importance changed from “” to “Low”

    I don't know about becomes. Is it rails thing or your own implementation? If it is your implementation then can you post the method?

  • Dim
  • Repository

    Repository November 11th, 2010 @ 06:17 PM

    • State changed from “new” to “resolved”

    (from [de2933e1a062f0752512eb0ec60f7217f4890f8c]) STI type is now updated when calling AR::Base.becomes on subclasses [#5953 state:resolved] https://github.com/rails/rails/commit/de2933e1a062f0752512eb0ec60f7...

  • José Valim
  • Andrew White

    Andrew White November 11th, 2010 @ 06:21 PM

    • State changed from “resolved” to “new”

    Looking at the docs it seems that becomes is more for temporarily mutating an instance so that it appears as its superclass for rendering purposes (partials, polymorphic routes, etc.). You're trying to use it the other way round - making a superclass become a subclass.

    There should be an official way of mutating an object to a different class and saving the change back to the database but I don't think becomes should be it.

  • Dim

    Dim November 11th, 2010 @ 06:29 PM

    Not sure, I think becomes is already doing most of the job pretty well, but it's certainly incomplete.

  • Santiago Pastorino

    Santiago Pastorino February 11th, 2011 @ 07:18 PM

    • State changed from “new” to “open”

    This issue has been automatically marked as stale because it has not been commented on for at least three months.

    The resources of the Rails core team are limited, and so we are asking for your help. If you can still reproduce this error on the 3-0-stable branch or on master, please reply with all of the information you have about it and add "[state:open]" to your comment. This will reopen the ticket for review. Likewise, if you feel that this is a very important feature for Rails to include, please reply with your explanation so we can consider it.

    Thank you for all your contributions, and we hope you will understand this step to focus our efforts where they are most helpful.

  • Santiago Pastorino

    Santiago Pastorino February 11th, 2011 @ 07:18 PM

    • State changed from “open” to “stale”
  • Mark Wilden

    Mark Wilden April 18th, 2011 @ 02:01 AM

    This may be stale, but it's still a problem. AFAICS, you can't update the type of an STI record.

    If a user changes an ArticleReference to a BookReference, I use #becomes on it, but then the update call tries to update a BookReference with that ID, and there isn't one. I think it's incorrect behavior to use the type column to find a single record - just the id should be used, as was apparently done in Rails < 3.

    My workaround is

    Reference.connection.execute "UPDATE `references` SET type = '#{@reference.type}' 
      WHERE id = '#{@reference.id}'"
    @reference.update_attributes params[:reference]
    
  • victorcoder

    victorcoder May 4th, 2011 @ 08:46 AM

    What's the status of this issue, it should be fixed?

    Thanks.

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Attachments

Referenced by

Pages