Possible to alias a belongs_to association in Rails?

38,039

Solution 1

No it doesn't look for company_id for instance change your code as follows

In Rails3

class Car < ActiveRecord::Base
   belongs_to :vendor
   belongs_to :company, :class_name => :Vendor,:foreign_key => "vendor_id"
end

In Rails4

We can use alias attribute.

alias_attribute :company, :vendor

Solution 2

In Rails 4, you should simply be able to add alias_attribute :company, :vendor to your model.

Solution 3

Short Version:

  1. Generate model with migration

    $ rails generate model Car vendor:references name:string ...

  2. Add following line in Car model i.e car.rb file

    class Car < ActiveRecord::Base
      belongs_to :company, :class_name => 'Vendor', :foreign_key => 'vendor_id'
    end
    
  3. Now you have @car.company instance method.

For a Detailed explanation read ahead [Optional if you understood the above !!]

Detailed Version:

The model Car will have an association with the model Vendor (which is obvious). So there should be a vendor_id in the table cars.

  1. In order to make sure that the field vendor_id is present in the cars table run the following on the command line. This will generate the right migration. The vendor:references is important. You can have any number of attributes after that.

    $ rails generate model Car vendor:references name:string

  2. Or else in the existing migration for create_table :cars just add the line t.references :vendor

    class CreateCars < ActiveRecord::Migration
      def change
        create_table :cars do |t|
          t.string :name
          ...
          t.references :vendor
          t.timestamps
        end
      end
    end
    
  3. The final thing that you need to do is edit the model Car. So add this code to your car.rb file

    class Car < ActiveRecord::Base
      belongs_to :company, :class_name => 'Vendor', :foreign_key => 'vendor_id'
    end
    

After you do the third step you will get the following instance methods for the model Car provided by Rails Associations

  1. @car.company

    • When you do @car.company it will return a #<Vendor ...> object. To find that #<Vendor ...> object it will go look for the vendor_id column in the cars table because you have mentioned :foreign_key => 'vendor_id'

    • You can set the company for a car instance by writing

      @car.company = @vendor || Vendor.find(params[:id]) #whichever Vendor object you want
      @car.save
      

      This will save the id of that Vendor object in the vendor_id field of the cars table.

Thank You.

Solution 4

class Car < ActiveRecord::Base
  belongs_to :vendor
  belongs_to :company, :class_name => :Vendor
end
Share:
38,039
at.
Author by

at.

Updated on May 31, 2020

Comments

  • at.
    at. almost 4 years

    I have a model with a belongs_to association:

    class Car < ActiveRecord::Base
      belongs_to :vendor
    end
    

    So I can call car.vendor. But I also want to call car.company! So, I have the following:

    class Car < ActiveRecord::Base
      belongs_to :vendor
      def company
        vendor
      end
    end
    

    but that doesn't solve the assignment situation car.company = 'ford', so I need to create another method for that. Is there a simple alias mechanism I can use for associations? Can I just use alias_method :company, :vendor and alias_method :company=, :vendor=?

  • at.
    at. over 10 years
    wouldn't this look for a company_id field in the database?
  • Hilder Vitor Lima Pereira
    Hilder Vitor Lima Pereira almost 9 years
    Good tip! Just to point: using alias_attribute makes still possible to access both the attributes company and vendor, while using only the relation belongs_to :company, :class_name => :Vendor,:foreign_key => "vendor_id" hides the attribute vendor.
  • wes.hysell
    wes.hysell about 8 years
    No, at least in Rails 4.2. After some testing, it appears that the column name is determined by the class used, not the association's attribute name. So belongs_to :company, class_name: :Vendor would search for a column in your table named vendor_id - whereas not specifying the class_name option will auto-resolve to use class name Company and would search for a company_id column. Nevertheless, it still may be considered better practice to supply the foreign_key: option to help eliminate future headaches.
  • Will I AM
    Will I AM almost 8 years
    Unfortunately reflect_on_association doesn't work with the latter.
  • Jerome
    Jerome over 7 years
    The rails 4 syntax is concise, but works if your syntax is picture perfect. By doing belongs_to :company, class_name: :Vendor, foreign_key: "vendor_id" you actually have a better handle on the syntax of your variables and can use that as an intermediary step to "succincty'