Rails association for two foreign keys for the same table in one table

Refresh

December 2018

Views

12k time

19

I am new to RoR and still playing with associations. I need to have two references to a particular model in another model. The scaffolded code doesn't work and I get a "uninitialized constant" error.

Generation commands:

script/generate scaffold BaseModel name:string
script/generate scaffold NewModel name:string base1:references base2:references
db:migrate

Generated models:

class NewModel < ActiveRecord::Base
     belongs_to :base1
     belongs_to :base2
end

and

class BaseModel < ActiveRecord::Base
     has_many :new_models # I added this line
end

When I try to create a new_model at /new_models/new, I tried both the ID and the name of the BaseModel but it does not work. The error I get is:

uninitialized constant NewModel::Base1

I guessed it maps the names, so in my create method, I tried to explicitly set the BaseModel instances:

@new_model = NewModel.new(params[:new_model])
@base1 = BaseModel.find(1) # this exists
@base2 = BaseModel.find(2) # this exists
@new_model.base1 = @base1  # This throws the same error as above

Is there anything I'm missing?

2 answers

31

Большинство Rails' магии приходит из конвенции по конфигурации. Называя вещи в соответствии с рекомендациями Rails может угадать в большинстве вариантов конфигурации. ActiveRecord :: Ассоциация не является исключением.

Первый аргумент любой ассоциации ActiveRecord это имя, которое будет использоваться в рамках модели. Это, как правило, название другой модели, это условность. По имени класса по умолчанию является единственным числом от имени ассоциации в CamelCase. Внешний ключ по умолчанию в ассоциации является объединение имя оканчивается с «_id». Если ваше имя ассоциации не совпадает с именем класса или внешний ключ с помощью этих шаблонов вы должны поставить их в качестве опции.

Это будет делать то, что вы хотите:

class NewModel
  belongs_to :base1, :class_name => "BaseModel"
  belongs_to :base2, :class_name => "BaseModel"
end

Лично я хотел бы дать Ассоциации более описательные имена, что base1 и BASE2. Что-то вроде этого:

Рейтинги таблицы: идентификатор, rater_id, rated_id, рейтинг

class Rating
  belongs_to :rater, :class_name => "User"
  belongs_to :rated_user, :class_name => "User", :foreign_key => "rated_id"
end

Другой пример может быть использован, но это было выбрано, чтобы подчеркнуть, когда вариант внешнего ключа необходим.

0

Символ передается belongs_toметоду должно быть в единственном числе имя другой модели. Так для примера, это будет:

class NewModel < ActiveRecord::Base 
  belongs_to :base_model 
end