Сохранение записи, основанной на двух таблицах - PullRequest
0 голосов
/ 24 марта 2020

Работа над моим первым приложением рельсов. У меня есть две модели: Альбомы и Треки.

При добавлении трека в альбом, мне нужен идентификатор альбома для сохранения. У меня есть collection_select, который извлекает все альбомы и перечисляет их с их идентификаторами в порядке убывания:

<%= form.collection_select :albums_id, Album.all.order(id: :desc), :id, :title, :include_blank => false %>

Это прекрасно работает, создавая html:

<select name="track[albums_id]" id="track_albums_id">
  <option value="11">Eleventh Album Title</option>
  <option value="10">Tenth Album Title</option>
  ...
</select>

Но когда я пытаюсь сохранить новую запись, я всегда получаю ошибку: Album must exist

Контроллер имеет:

 def create
   @track = Track.new(track_params)

   respond_to do |format|
     if @track.save
       format.html { redirect_to @track, notice: 'Track added.' }
       format.json { render :show, status: :created, location: @track }
     else
       @page_title = 'ERROR - Add Track'
       format.html { render :new }
       format.json { render json: @track.errors, status: :unprocessable_entity }
     end
   end
 end

и track_params относится к:

private
  def track_params
    params.require(:track).permit(:albums_id, :title, :track_number, :track_url)
  end

Модели:

album.rb

class Album < ApplicationRecord
    has_many :tracks
    validates :title, presence: true
    validates :release_year, presence: true
    has_one_attached :photo
end

track.rb

class Track < ApplicationRecord
    belongs_to :album
    validates :title, presence: true
    validates :track_number, presence: true
    validates :track_url, presence: true
end

rout.rb

Rails.application.routes.draw do
  resources :tracks
  root 'pages#about'

  get 'signup', to: 'users#new', as: 'signup'
  get 'login', to: 'sessions#new', as: 'login'
  get 'logout', to: 'sessions#destroy', as: 'logout'
  get 'contact', to: 'messages#new', as: 'contact'
  get 'sessions', to: 'sessions#new'
  get 'dashboard', to: 'pages#dashboard', as: 'dashboard'

  resources :videos
  resources :gigs
  resources :photos
  resources :albums
  resources :users
  resources :groups
  resources :messages
  resources :sessions, only: [:new, :create, :destroy]

  post "/delayed_job" => DelayedJobWeb, :anchor => false
end

Все значения кроме :albums_id принимаются. Выбранное значение в collection_select всегда игнорируется и вызывает ошибку, которая препятствует сохранению дорожки. albums_id - это имя столбца базы данных, созданное rails в результате belongs_to: albums.

Что я делаю плохо?

ОБНОВЛЕНИЕ: Миграции

... create_albums.rb:

class CreateAlbums < ActiveRecord::Migration[5.2]
  def change
    create_table :albums do |t|
      t.string :artist
      t.string :copyright
      t.string :title
      t.date :release_year
      t.text :comment

      t.timestamps
    end
  end
end

... create_tracks.rb:

class CreateTracks < ActiveRecord::Migration[5.2]
  def change
    create_table :tracks do |t|
      t.belongs_to :albums
      t.string :title
      t.integer :track_number, :default => 1
      t.string :track_url

      t.timestamps
    end
  end
end

1 Ответ

2 голосов
/ 24 марта 2020

То, что вы можете сделать, это следовать соглашению о рельсах, а не обходить его. Вы можете удалить столбец album_id (есть способ сделать эту работу, но опять же это обходной путь и не рекомендуется), поэтому вместо этого вы можете сначала удалить столбец album_id, а затем добавить album_id, как показано ниже:

rails g migration DropColumnFromTrack

Затем в сгенерированном файле миграции:

remove_column :tracks, :albums_id

Затем выполните: (Предполагая, что в этом столбце нет данных)

rails db:migrate

Теперь сгенерируйте столбец album_id: Здесь ниже Альбом: ссылки означает, что мы говорим, что запись в таблице дорожек принадлежит таблице альбомов.

rails g migration AddAlbumToTrack album:references

И выполните

rails db:migrate

Убедитесь, что в таблице дорожек есть столбец album_id и теперь ассоциации должны работать правильно

...