简体   繁体   English

更新has_many:通过与Rails表单关联

[英]Updating a has_many :through association with a rails form

I'm trying to update the form for a Song model that has multiple Genres through a song_genre_relationships model. 我正在尝试通过song_genre_relationships模型为具有多个流派的Song模型更新表单。 I'd prefer to update the genre id's for any given song through an array in the form field. 我更愿意通过form字段中的数组更新任何给定歌曲的流派ID。

I suspect my controller is off, but I'm still pretty new to Rails and am unsure. 我怀疑我的控制器已关闭,但是我对Rails还是很陌生,并且不确定。

Here are my models, form and controller. 这是我的模型,表格和控制器。

EDITED BASED ON meagar's RESPONSE BELOW. 根据以下meagar的响应进行编辑。

song.rb song.rb

class Song < ActiveRecord::Base

    has_many :song_genre_relationships
    has_many :genres, :through => :song_genre_relationships

end

song_genre_relationships.rb song_genre_relationships.rb

class SongGenreRelationship < ActiveRecord::Base

    belongs_to :song
    belongs_to :genre

end

genre.rb 体裁

class Genre < ActiveRecord::Base

    has_many :song_genre_relationships
    has_many :songs, :through => :song_genre_relationships

end

song_controller.rb song_controller.rb

class SongController < ApplicationController

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

    relationships = @song.song_genre_relationships
    @genres = Genre.all
    @genres.each do |genre|
        unless relationships.detect { |g| g.genre_id == genre.id }
            relationships.build genre_id: genre.id
        end
    end

    if @song.update_attributes(song_params)

        flash[:notice] = "Song updated successfully."

        redirect_to(:action => 'index')
    else
        render('edit')
    end
end

private
def song_params
    params.require(:song).permit(:name, :genre_ids => [])
end

_form.html.erb (song form) _form.html.erb(歌曲形式)

<%= form_for(@song) do |f| %>

    <%= f.label :name, 'Title' %>
    <%= f.text_field :name %>

    <%= f.label :genre_ids, 'Genres' %>
    <%= f.text_area :genre_ids %>


<%= f.submit %>
<% end %>

This is wrong: 这是错误的:

  @genres = params[:song][:genre_ids]
    Array(@genres).each do |genre|
        unless relationships.detect { |g| g.genre_id == genre.id }
            relationships.build genre_id: genre
        end
    end

params[:song][:genre_ids] is a string. params[:song][:genre_ids]是一个字符串。 It contains, in your example, "[<whatever id's input to the form>]" . 在您的示例中,它包含"[<whatever id's input to the form>]"

You're wrapping it in an array with Array(@genres) . 您使用Array(@genres)将其包装在一个数组中。 Now, you have an array containing a single item, which is the string. 现在,您有一个包含单个项目(即字符串)的数组。 Then you iterate over that single item, placing it into genre inside the loop 然后,您遍历该单个项目,并将其放入循环内的genre

Then you test g.genre_id == genre.id . 然后测试g.genre_id == genre.id genre is that string, and you're invoking .id on it, hence your error. genre是该字符串,并且您正在对其调用.id ,因此会出现错误。

It's impossible to tell what you're trying to do, but you definitely cannot invoke .id on a string and expect to get the ID of some database record back. 无法说出您要执行的操作,但是您绝对不能在字符串上调用.id并期望获得一些数据库记录的ID。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM