accepts_nested_attributes_for противоречит логике реляционной базы данных c в Rails - PullRequest
0 голосов
/ 27 февраля 2020

Ruby в логи модели Rails c конфликтует с логикой реляционной базы данных c.

В Ruby в Rails модель, обладающая belongs_to, будет иметь внешний ключ в база данных. Итак, модель:

class Student < ApplicationRecord
    belongs_to :university
end

class University < ApplicationRecord
    has_many :university
end

будет иметь файл миграции:

class CreateStudents < ActiveRecord::Migration[6.0]
    t.string :name
    t.references :university, foreign_key: true
end

class CreateUniversities < ActiveRecord::Migration[6.0]
    t.string :name
end

И, по логике, студент будет иметь в базе данных Foreign_key университета, например:

Student
-id int (PK)
-name varchar
-University_id int (FK)

University
-id int (PK)
-name varchar

Пока все хорошо

Проблема возникает, когда я хочу accepts_nested_attributes_for в модели студента для ссылки на университет в _form.html.erb. Чтобы использовать его, модель хоста, в данном случае Student, должна иметь has_one вместо belongs_to для таблицы ссылок. Таким образом, это стало бы:

class Student < ApplicationRecord
    has_one :university
    accepts_nested_attributes_for :university
end

Обратите внимание, как для использования accepts_nested_attributes_for для ссылки на университет модель Student MUST заменяет belongs_to :university на has_one :university, и университет будет иметь belongs_to :student вместо has_many :student.

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

class CreateStudents < ActiveRecord::Migration[6.0]
    t.string :name
end

class CreateUniversities < ActiveRecord::Migration[6.0]
    t.string :name
    t.references :student, foreign_key: true
end

И база данных будет принудительно иметь вид:

Student
-id int (PK)
-name varchar

University
-id int (PK)
-name varchar
-Student_id int (FK)

Что не так, потому что между университетом и студентом должны быть отношения один ко многим, а не наоборот.

Итак, есть ли способ использовать accepts_nested_attributes_for, не путая логику реляционной базы данных c, если принудительно инвертировать отношения в моделях?

Ответы [ 2 ]

1 голос
/ 27 февраля 2020

accepts_nested_attributes_for Вложенные атрибуты позволяют сохранять атрибуты в связанных записях через родительский элемент.

Таким образом, у вас может быть небольшая путаница относительно того, какой из них вы хотите использовать в качестве родительского. , Если вы сделаете учащегося родителем с вложенными атрибутами для университета, вы не будете ссылаться на университет, а просто создадите новую запись об университете или обновите существующую с помощью вложенных атрибутов, которые вы использовали в форме студента.

One-to-one

Consider a Member model that has one Avatar:

class Member < ActiveRecord::Base
  has_one :avatar
  accepts_nested_attributes_for :avatar
end

Enabling nested attributes on a one-to-one association allows you to create the member and avatar in one go:

params = { member: { name: 'Jack', avatar_attributes: { icon: 'smiling' } } }
member = Member.create(params[:member])
member.avatar.id # => 2
member.avatar.icon # => 'smiling'

Таким образом, вы будете обновлять / создавать новые университетские записи только для каждого студента, для которого вы использовали эти вложенные атрибуты.

Вот для одного ко многим:

One-to-many

Consider a member that has a number of posts:

class Member < ActiveRecord::Base
  has_many :posts
  accepts_nested_attributes_for :posts
end

You can now set or update attributes on the associated posts through an attribute hash for a member: include the key :posts_attributes with an array of hashes of post attributes as a value.

For each hash that does not have an id key a new record will be instantiated, unless the hash also contains a _destroy key that evaluates to true.

params = { member: {
  name: 'joe', posts_attributes: [
    { title: 'Kari, the awesome Ruby documentation browser!' },
    { title: 'The egalitarian assumption of the modern citizen' },
    { title: '', _destroy: '1' } # this will be ignored
  ]
}}

member = Member.create(params[:member])
member.posts.length # => 2
member.posts.first.title # => 'Kari, the awesome Ruby documentation browser!'
member.posts.second.title # => 'The egalitarian assumption of the modern citizen'

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

Если вы просто ищете ссылку, вы, по сути, имеете ее в своем первом примере и можете просто немного изменить свои маршруты, чтобы студент ссылался на университет .

Затем, когда у вас есть вложенные маршруты, вы можете просто немного поработать с частичной формой. Вот парень, который делает именно это

Так что, может быть, если я далеко, опишите, почему, когда вы создаете / обновляете студента, вы хотите создать / обновить университет. Если это именно то, что вы хотите сделать.

Это поможет другим в вашем контексте немного больше и поможет другим понять ваше намерение с помощью вложенных атрибутов.

Добавьте, например, частичную форму и Объясните свою цель.

РЕДАКТИРОВАТЬ: Как пунт, вы можете, возможно, взглянуть на имеет и принадлежит ко многим ассоциациям. Этот учебник говорит о вложенных атрибутах с ассоциация многих ко многим. Но так как я не уверен, что именно вы после этого, может или не может помочь.

Похоже, другой пунт говорит, что вы, возможно, захотите изменить студенческий послужной список, когда вы обновите их. Таким образом, вы бы хотели, чтобы студент принадлежал к университету, а в университете было много студентов, но при этом у него было много университетских записей, и у студента было много / есть одна университетская запись и запись, принадлежащая обоим. aka: this

Тогда вы можете попросить студента принять вложенные атрибуты для университетской записи / с.

0 голосов
/ 06 марта 2020

Я вижу, что ДЕЙСТВИТЕЛЬНО совершил ошибку, пытаясь объяснить свои сомнения (это мой первый вопрос, который я усвоил из своей ошибки).

Конечной целью было узнать:

Могу ли я использовать acceptpts_nested_attributes_for, когда has_one вместо has_one *1008* или has_many ?

Итак, ответ да:

class Student < ApplicationRecord
    belongs_to :university
    accepts_nested_attributes_for :university
end

В контроллере ученика должна быть сборка _:

  def new
    @student = Student.new
    @student.build_university
  end

Я ДЕЙСТВИТЕЛЬНО, ДЕЙСТВИТЕЛЬНО, ДЕЙСТВИТЕЛЬНО опечатал мой вопрос, и я прошу прощения за него.

Спасибо за все ваши ответы.

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