保存依赖于两个表的记录

Saving a record that relies on two tables

正在开发我的第一个 rails 应用程序。 我有两个模型:专辑和曲目。

将曲目添加到专辑时,我需要专辑 ID 才能保存。 我有一个 collection_select 可以提取所有相册并按降序列出它们的 ID:

<%= 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

routes.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

您可以做的是遵循 rails 惯例,而不是绕过它。 您可以删除 albums_id 列(有一种方法可以使此工作正常进行,但同样是一种变通方法,但不可取)因此,yiu 可以先删除 albums_id 列,然后添加 album_id 如下所示:

rails g migration DropColumnFromTrack

然后在生成的迁移文件中:

remove_column :tracks, :albums_id

然后执行:(假设您在该列中没有数据)

rails db:migrate

现在生成 album_id 列: 下面 album:references 表示我们告诉曲目 table 中的记录属于专辑 table.

rails g migration AddAlbumToTrack album:references

然后做

rails db:migrate

确保您的曲目中有一个 album_id 列 table,现在关联应该可以正常工作了