我正在通过Rails教程创建一个詹姆斯邦德电影数据库。我有两个模型,movie.rb和theme_song.rb。这两者有以下关联:
class Movie < ApplicationRecord
has_one :theme_song
end
class ThemeSong < ApplicationRecord
belongs_to :movie
end
我还在routes.rb文件中表示了这个关联:
resources :movies do
resources :theme_songs
end
我需要让用户将附加影片的细节添加到数据库中,包括一般电影信息和有关主题歌的信息。一般信息属于Movie模型,主题歌信息属于ThemeSong模型,如下面的迁移所示:
create_table :movies do |t|
t.string :title
t.datetime :release_date
t.text :plot
t.timestamps
end
create_table :theme_songs do |t|
t.string :song
t.string :artist
t.references :movie, foreign_key: true
t.timestamps
end
我有一个movies_controller.rb控制器和一个链接到控制器的new.html.erb视图。 new.html.erb视图将以下格式编码到其中:
<%= form_with model: @movie, local: true do |form| %>
<p><strong>Movie Details</strong></p>
<p>
<%= form.label 'Title:' %>
<%= form.text_field :title %>
</p>
<p>
<%= form.label 'Release date:' %>
<%= form.text_field :release_date %>
</p>
<p>
<%= form.label 'Plot:' %>
<%= form.text_area :plot %>
</p>
<p><strong>Soundtrack</strong></p>
<p>
<%= form.label 'Theme song:' %>
<%= form.text_area :song %>
</p>
<p>
<%= form.label 'Artist:' %>
<%= form.text_area :artist %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
我需要用户能够填写该表单,提交表单,以及我的控制器创建操作以在Movie中添加新记录和一般信息,在ThemeSong中添加带有音轨信息的新记录,两个记录都已链接在协会。
这是我到目前为止在我的movies_controller.rb的相关方法中得到的代码:
def create
@movie = Movie.new(movie_params)
if @movie.save
redirect_to @movie
else
render 'new'
end
end
private
def movie_params
params.require(:movie).permit(:title, :release_date, :plot, :song, :artist)
end
有人能告诉我在create / movie_params方法中需要哪些代码吗?或者如果我以完全错误的方式处理它,如果是这样,我应该如何实现它?
我正在使用Rails 5.1.4
答案 0 :(得分:0)
您需要使用的是accepts_nested_attributes_for
,它允许您在theme_song
表单中使用movie
的嵌套表单:
将其添加到您的Movie
型号:
class Movie < ApplicationRecord
has_one :theme_song
accepts_nested_attributes_for :theme_song
end
电影控制器中的:
def new
@movie = Movie.new
@movie.build_theme_song
end
private
def movie_params
params.require(:movie).permit(:title, :release_date, :plot, :song, :artist, theme_song_attributes: [:song, :artist])
end
最后,在movie
表单中使用fields_for
帮助器为电影theme_song
添加字段:
<%= form_for @movie do |f| %>
theme song:
<ul>
<%= f.fields_for @movie.theme_song do |theme_song_form| %>
<li>
<%= theme_song_form.label :song %>
<%= theme_song_form.text_field :song %>
...
</li>
<% end %>
</ul>
<% end %>
现在,当您提交表单时,它会为该电影创建movie
条记录和theme_song
记录。
答案 1 :(得分:0)
没有为theme_song模型提供信息,需要创建哪些字段或哪些数据,但您可能不希望这两个表中的数据重复。
您没有采用错误的方式,将两组数据添加到单个表单可能最简单,使用accepts_nested_attributes。然后告诉你的movies_controller参数也接受嵌套特征。然后它以魔术方式以相应的方式保存数据。
class Movie < ApplicationRecord
has_one :theme_song
accepts_nested_attributes_for :theme_song
end
<%= form_with model: @movie, local: true do |form| %>
<p><strong>Movie Details</strong></p>
<p>
<%= form.label 'Title:' %>
<%= form.text_field :title %>
</p>
<p>
<%= form.label 'Release date:' %>
<%= form.text_field :release_date %>
</p>
<p>
<%= form.label 'Plot:' %>
<%= form.text_area :plot %>
</p>
<p><strong>Soundtrack</strong></p>
<%= form.fields_for :theme_song do |theme_song| %>
<p>
<%= theme_song.label 'Theme song:' %>
<%= theme_song.text_area :song %>
</p>
<p>
<%= theme_song.label 'Artist:' %>
<%= theme_song.text_area :artist %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
def create
@movie = Movie.new(movie_params)
if @movie.save
redirect_to @movie
else
render 'new'
end
end
def new
@movie = Movie.new
@movie.build_theme_song
end
private
def movie_params
params.require(:movie).permit(:title, :release_date, :plot, :song, :artist, theme_song_attributes: [:song, :artist, :id])
end
这里要注意两件事,第一件事是在新操作中你需要确保构建嵌套记录。其次,嵌套属性以数组的形式添加到参数中,它必须是这样的。
使用此方法有其局限性。您应该知道这意味着如果两部不同的电影使用相同的主题曲,您将拥有2首电影唱片和2首主题曲唱片。这可能会让它更慢/更难说'#34;向我展示这首歌所在的所有电影&#34;,因为那时你必须考虑用户错误和按名称搜索的拼写。您可能会发现,在将来,最好有一个电影记录,一个主题歌曲记录和一个MovieThemeSongs记录,它基本上加入了这两个记录。