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

[WIP] Aliased foreign keys in association definitions #20682

Closed

Conversation

k0nserv
Copy link

@k0nserv k0nserv commented Jun 24, 2015

Hello,

this is first step in a feature I'd like to implement. My post on the rails-core mailing list is here https://groups.google.com/forum/?fromgroups#!topic/rubyonrails-core/PQCBPn_fK-w

This PR is intentionally not done because it is still not clear if this is a change that is consider warranted for the problem it solves. I've implemented only support for belongs_to to get a grasp on the change and how it affects performance

Problem

When using an aliased attribute as the foreign key for a association rails does not behave as expected.

Example

class Pet < ActiveRecord::Base
  alias_attribute :owner_id :OwnerID

  belongs_to :owner # This association will not work
end

Suggested fix

Places where the value of the foreign key in the owner is determined use _read_attribute or ActiveRecord::Base.[] this bypasses aliased attributes completely. To combat this I suggest that an explicit check or fallback is added to consider aliased attributes

Performance

Doing the extra work to figure out wether the foreign_key is aliased will take some extra time. Depending on how it is implemented the work could be a small constant slowdown or a heavier slowdown in edge cases, but with a very small effect on the most common case. The following examples uses active_record/lib/active_record/associations/belongs_to_association.rb#foreign_key_present? to illustrate the change and it's impact on performance.

Edge case slowdown

def foreign_key_present?
  key = owner._read_attribute(reflection.foreign_key)
  # Extra check if the foreign key is aliased or the value is nil
  unless key
    real_key = owner.class.attribute_alias(reflection.foreign_key)
    key = owner._read_attribute(real_key) if real_key
  end

   key
end

Constant slowdown

def foreign_key_present?
  aliased_key = owner.class.attribute_alias(reflection.foreign_key)
  real_key = aliased_key ? aliased_key : foreign_key

  key = owner._read_attribute(real_key)
end

@khiav223577
Copy link

Want this feature!

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

Successfully merging this pull request may close these issues.

None yet

4 participants