В таблице соединений есть два множественных слова. Как правильно назвать модели и миграции; для того, чтобы уничтожить сирот на столике Активная запись - PullRequest
0 голосов
/ 07 мая 2018

Хорошо, оставив в стороне тот факт, что спрашивать, как "уничтожить сирот" на доске чата - это просто зло, вот мой технический вопрос:

Я делаю простой блог-сайт, используя Activerecord и Sinatra (и я новичок в обоих). У меня есть отношение «многие ко многим» между моделью Post и моделью Tag, и я получаю ошибки, которые мне не удалось разобрать. Наконец, я упорядочил модели и миграцию так, чтобы не было ошибок; однако когда я уничтожаю экземпляр тега, ассоциации в таблице posts_tags остаются на месте (существуют как сироты), и я хочу знать, как их уничтожить (кий злую музыку).

Может ли кто-нибудь помочь мне с этим?

Вот моя миграция для всех трех таблиц:

class CreatePostsTable < ActiveRecord::Migration[5.2]
  def change
    create_table :posts do |t|
      t.string :title, default: 'title here'
      t.string :content, default: 'content here'
      t.belongs_to :blog, index: true
      t.timestamps
    end
  end
end

class CreateTagTable < ActiveRecord::Migration[5.2]
  def change
    create_table :tags do |t|
      t.string :name, unique: true
    end
  end
end

class CreatePostsTagsTable < ActiveRecord::Migration[5.2]
  def change
    create_table :posts_tags, :id => false do |t|
      t.belongs_to :tag, index: true
      t.belongs_to :post, index: true
      # t.integer :post_id
      # t.integer :tag_id
    end
  end
end

А вот мои три модели:

file-name: Post_Tag (я назвал и переименовал этот класс и имя файла в течение пары дней).

class PostsTag < ActiveRecord::Base
   # self.table_name = "posts_tags"  #had to add this line for seed file not to give errors
    belongs_to :post
    belongs_to :tag
end

class Post < ActiveRecord::Base
    belongs_to :blog
    has_many :posts_tags
    has_many :tags, :through => :posts_tags
    has_many :comments, dependent: :destroy  
end

class Tag < ActiveRecord::Base
    has_many :posts_tags
    has_many :posts, :through => :posts_tags
    # has_and_belongs_to_many :posts, :through => :posts_tags
end

Эта конфигурация не дает мне ошибки, когда я ищу теги поста или посты тега, НО, когда я делаю @tag = Tag.find_by_id (1) @ tag.destroy, таблица "posts_tags" остается все еще имеющей все из tag_id == 1 строк еще там. Когда я пытаюсь уничтожить их, я получаю ошибки (которые, по-моему, могут также разрушить ассоциации).

Кто-нибудь знает, как это исправить? Можно ли просто удалить модель PostsTag вместе?

В документации Activerecord используется пример, в котором таблица соединений представляет собой одно слово, поэтому я не смог найти там ответ.

Я видел, что некоторые люди просто не делали модель для стола соединения. Когда я удалил свою модель таблицы соединений, я получил эту ошибку:

@post = Post.find_by_id(1)
@post.tags.each do |tag|    
    p tag.name    
end

NameError at / неинициализированная константа Tag :: PostsTag

Спасибо за любую помощь!

#

Вторая фаза вопроса:

После подсказки, что я могу попробовать добавить этот код в мои модели:

class Post < ActiveRecord::Base
    has_many :posts_tags, dependent: :destroy
class Tag < ActiveRecord::Base

Я запускаю это в файле моего сервера / приложения:

delete "/tag/destroy" do
        body = JSON.parse request.body.read  # body: {id: number} or {name: string}
        @tag_to_destroy = Tag.where(body)[0] 
        @tag_to_destroy.destroy
redirect "/tag"
end

Я отправляю этот запрос через почтальона:

http://localhost:4567/tag/destroy
body of request:
{
    "id": 12
}

И я получаю эту ошибку: (хотя в базе данных posts_tags есть строки с tag_id = 12, post_id = VariousNumbers):

== Sinatra (v2.0.1) вышла на 4567 этап разработки для резервного копирования из Puma Пума стартует в одиночном режиме ... * Версия 3.11.4 (ruby 2.5.1-p57), кодовое название: Love Song * Минимальное количество тем: 0, максимальное количество тем: 16 * Environment: development * Прослушивание tcp: // localhost: 4567 Используйте Ctrl-C, чтобы остановить D, [2018-05-07T10: 54: 19.604906 # 99099] ОТЛАДКА -: Загрузка тегов (0,5 мс) ВЫБРАТЬ «теги». * ИЗ «тегов» ГДЕ «t ags "." id "= $ 1 [[" id ", 12]] D, [2018-05-07T10: 54: 19.617955 # 99099] DEBUG -: (0,3 мс) НАЧАЛО D, [2018-05-07T10: 54: 19.633736 # 99099] ОТЛАДКА -: нагрузка на пост-тег (1,5 мс) ВЫБРАТЬ "posts_tags". * FROM "pos ts_tags "ГДЕ" posts_tags "." tag_id "= $ 1 [[" tag_id ", 12]] D, [2018-05-07T10: 54: 19.642305 # 99099] ОТЛАДКА -: PostsTag Destroy (1.6ms) УДАЛИТЬ ИЗ "posts_tags" ГДЕ "posts_tags". "" IS NULL D, [2018-05-07T10: 54: 19.642685 # 99099] DEBUG -: (0,2 мс) ROLLBACK 2018-05-07 10:54:19 - ActiveRecord :: StatementInvalid - PG :: SyntaxError: ОШИБКА: идентификатор с разделителями нулевой длины в «или около» ЛИНИЯ 1: УДАЛИТЬ ИЗ "posts_tags" ГДЕ "posts_tags". "" НУЛЬ ^ : DELETE FROM "posts_tags" ГДЕ "posts_tags". "" НУЛЬ: /Users/maiya/.rvm/gems/ruby-2.5.1/gems/activerecord-5.2.0/lib/active_record/connection_adapters/postgresql_adapter.rb:603:in `async_exec '

Обновление вопроса:

Миграция таблицы соединений ранее:

  create_table :posts_tags  :id => false do |t|
      t.belongs_to :tag, index: true   
       # comment: the above line creates: t.integer :post_id
      t.belongs_to :post, index: true
       # comment: the above line creates: t.integer :tag_id  
  end

1 Ответ

0 голосов
/ 07 мая 2018

Теперь все в порядке с вашими миграциями и моделями, вам просто нужно изменить в Post и Tag моделях:

has_many :posts_tags

до

has_many :posts_tags, dependent: :destroy

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

Также рекомендуется откатить миграцию, добавить опцию foreign_key: true к t.belongs_to строкам и перенести ее снова. Эта опция обеспечит ссылочную целостность на уровне БД.

UPDATE:

has_and_belongs_to_many (HABTM) не работает с опцией through, вы смешиваете ее с ассоциацией has_many. Пожалуйста, прочитайте об этом больше в руководствах

Чтобы все заработало, вам нужно:

  • удалить :id => false параметр из CreatePostsTagsTable миграции
  • перенести или сбросить и воссоздать дБ
  • изменить has_and_belongs_to_many <...>, :through => :posts_tags на has_many <...>, :through => :posts_tags в моделях Tag и Post

P.S. По общему правилу все имена файлов в ruby ​​указаны в нижнем регистре змеи, это должно быть `posts_tag.rb ', а не' Posts_Tag.rb '

...