2016-04-29 108 views
2

我有一個「歌曲」和「藝術家」模型,我通過has_many:through關係加入。在命中 「創造的歌曲」 我得到這個錯誤持續:ControllerNameController中的ActiveRecord :: StatementInvalid#create SQLite3 :: SQLException:no such column:

  • 的ActiveRecord :: StatementInvalid在SongsController#創建 的SQLite3 ::的SQLException:沒有這樣的列:songs.artist:SELECT 1 AS一個 FROM「歌曲「WHERE(」 詩經」, 「名」= '這麼多更多', 「歌曲」, 「藝術家」 IS NULL)LIMIT 1

這裏從模型代碼和視圖

song.rb

class Song < ActiveRecord::Base 
belongs_to :genre 

has_many :artists_songs 
has_many :artists, :through => :artists_songs 

has_attached_file :image, styles: { large: "600x600>", medium: "300x300>", thumb: "150x150#{}" }, default_url: "/images/:style/missing.png" 
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/ 

accepts_nested_attributes_for :artists, allow_destroy: true 
accepts_nested_attributes_for :artists_songs, allow_destroy: true 

validates :name, :presence => true, uniqueness: { scope: :artist } #Unique names in the scope of PARENT 
#4now 'featured, description, genre_id, video' is missing because they aren't really a must, the rest perhaps are 
validates :year, :lyrics, :country, :image, :presence => true 

artist.rb

class Artist < ActiveRecord::Base 
belongs_to :country 

has_many :artists_songs 
has_many :songs, :through => :artists_songs 

has_attached_file :image, styles: { large: "600x600>", medium: "300x300>", thumb: "150x150#{}" }, default_url: "/images/:style/missing.png" 
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/ 

validates :name, :presence => true, uniqueness: true 
validates :country_id, :image, :presence => true 

artists_song.rb 「歌曲」 和 「藝術家」 之間的接合模型

class ArtistsSong < ActiveRecord::Base 
    belongs_to :song 
    belongs_to :artist 
end 

songs_controller.rb

class SongsController < ApplicationController 
before_action :find_song, only: [:show, :edit, :update, :destroy] 

def index 
    @songs = Song.all 
end 

def new 
    @song = Song.new 
    @song.artists.build 
    #@genres = Genre.all.map{|c| [ c.name, c.id ] } 
end 

def create 
    @song = Song.new(song_params) 
    if @song.save 
     redirect_to @song, notice: 'Successfully added a song.' 
    else 
     render 'index' 
    end 
end 

def show 

end 

def update 
    if @song.update(song_params) 
     redirect_to @song, notice: 'Successfully updated the song.' 
    else 
     render 'edit', notice: 'Unable to save the changes' 
    end 
end 

def edit 
end 

def destroy 
end 

#private methods/functions 
private 

#In this private method, the artists attributes are passed to be created via the Song model 
def song_params 
    params.require(:song).permit(:name, :featured, :year, :lyrics, :description, :video, :image, :genre_id, :artists_song_list, artists_attributes: [ :name, :image, :country_id ]) 
end 

def find_song 
    @song = Song.find(params[:id]) 
end 

new.html.erb(-songs_controller)

<div class="content"> 
<%= form_for @song, html: { multipart: true } do |f| %> 

    <% if @song.errors.any? %> 
     <div> 
      <%= @song.errors.count %> 
      Prevented this song from saving 
      <ul> 
       <% @song.errors.full_messages.each do |msg| %> 
        <li><%= msg %></li> 
       <% end %> 
      </ul> 
     </div> 
    <% end %> 

    <div class="field"> 
     <%= f.label :name %> 
     <%= f.text_field :name %><br> 
    </div> 

    <div class="artist-fields"> 
     <h2>Artist(s)</h2> 
     <div class="field"> 
      <%= f.fields_for :artists do |artists_for_form| %> 
       <%= render 'artist_fields', f: artists_for_form %> 
      <% end %> 
     </div> 
    </div> 

    <div class="field"> 
     <%= f.label :featured %> 
     <%= f.text_field :featured%><br> 
    </div> 
    <div class="field"> 
     <%= f.label :lyrics %> 
     <%= f.text_area :lyrics %><br> 
    </div> 

    <div class="field"> 
     <%= f.label :genre %> 
     <%= select_tag(:genre_id, options_for_select(@genres), :prompt => "Select one!") %> 
    </div> 


    <div class="field"> 
     <%= f.label :description %> 
     <%= f.text_area :description %><br> 
    </div> 
    <div class="field"> 
     <%= f.label :year %> 
     <%= f.text_field :year %><br> 
    </div> 

    <div class="field"> 
     <%= f.label :video %> 
     <%= f.text_field :video %><br> 
    </div> 

    <div class="field"> 
     <%= f.label :image %> 
     <%= f.file_field :image %> 
    </div> 

    <div class"btn"> 
     <%= f.submit %> 
    </div> 

    <%= link_to "Back", root_path %> 

<% end %> 

我什麼,我做錯了,如何正確地做我在rails 4中實現has_many:through關係?

COLUMN_NAMES爲三個表(歌曲,藝術家,ArtistsSong)

irb(main):001:0> Song.column_names 
=> ["id", "name", "featured", "lyrics", "description", "comments", "created_at", "updated_at", "video", "year", "image_file_name", "image_content_type", "image_file_size", "image_updated_at", "genre_id"] 

irb(main):002:0> Artist.column_names 
=> ["id", "name", "created_at", "updated_at", "country_id", "—force", "image_file_name", "image_content_type", "image_file_size", "image_updated_at"] 

irb(main):003:0> ArtistsSong.column_names 
=> ["id", "song_id", "artist_id", "created_at", "updated_at"] 
+0

你是否運行過你的遷移?你的schema.rb是否反映了所需的表和字段? – Alfie

+0

@Alfie是的,我沒有運行所有的遷移和計數器檢查所有3個表的列名。 – MulleOne

+0

+我附加了每個表的控制檯輸出column_names ... – MulleOne

回答

0

通過包括artists_songs_attributes[:id, artist_id, song_id]song_params方法songs_controller,有可能成功地添加歌曲與所需許多一對多表格是通過加入表artists_song的歌曲藝術家之間的關係

因此,與其這樣:

def song_params 
     params.require(:song).permit(:name, :featured, :year, :lyrics, :description, :video, :image, :genre_id, :artists_song_list, artists_attributes: [ :name, :image, :country_id ]) 
    end 

這工作:

def song_params 
     params.require(:song).permit(:name, :featured, :year, :lyrics, :description, :video, :image, :genre_id, :artists_song_list, artists_attributes: [ :name, :image, :country_id ], artists_songs_attributes[:id, artist_id, song_id]) 
    end 

我還是新的,讓學習Ruby on Rails框架,因此,根據我的瞭解甚少,到目前爲止,需要將artists_songs_attributes [:id, artist_id, song_id]傳遞給加入表(artists_song)以創建實際創建兩個表的創建行之間的鏈接的行(藝術家 & song)。

相關問題