Allow overring of primary_key to look at from a record that belongs_to :polymorphic => true #2240

Closed
ramontayag opened this Issue Jul 24, 2011 · 2 comments

Projects

None yet

2 participants

@ramontayag

I couldn't find a way to explain what I want to do properly in the title, so here's to hoping that someone will read the body and have a short discussion with me. I understand why many contributions don't get into Rails core, so I'm putting it up here with an explanation of what I want to do. This way, I won't be doing a bunch of work for nothing. If someone shows interest, then I'll submit a pull request.

Essentially, I want to be able to specify what column to find by from a record that belongs_to (in a polymorphic relationship) another object. I can explain this better in code. The change I was thinking of was something like this in ActiveRecord::Associations::BelongsToPolymorphicAssociation#find_target:

    def find_target
      return nil if association_class.nil?

      finder_method = :"find"
      finder_method = :"find_by_#{@reflection.options[:primary_key]}" if @reflection.options[:primary_key]
      target =
        if @reflection.options[:conditions]
          association_class.send(finder_method,
            @owner[@reflection.primary_key_name],
            :select     => @reflection.options[:select],
            :conditions => conditions,
            :include    => @reflection.options[:include]
          )
        else
          association_class.send(finder_method, @owner[@reflection.primary_key_name], :select => @reflection.options[:select], :include => @reflection.options[:include])
        end
      set_inverse_instance(target, @owner)
      target
    end

Of course, it'll be more robust and with tests. But this way, you can set the what column to look at like this:

class Image < AR::Base
  belongs_to :imageable, :polymorphic => true, :primary_key => :some_other_column
end

So if you call @image.imageable, it will essentially do something like this:

@image.imageable_type.constantize.find_by_some_other_column(...)

What do you think?

@kimf

+1

@ramontayag

@kimf, it looks like it's in Rails 3.1! So I don't need to put it on Rails 3.0.x. We can just monkey patch it in the mean time.

def test_polymorphic_assignment_with_primary_key_updates_foreign_id_field_for_new_and_saved_records
  essay = Essay.new
  saved_writer = Author.create(:name => "David")
  new_writer = Author.new

  essay.writer = saved_writer
  assert_equal saved_writer.name, essay.writer_id

  essay.writer = new_writer
  assert_nil essay.writer_id
end
@ramontayag ramontayag closed this Jul 28, 2011
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment