Rails中Movies与Schedules关联的new和create方法实例化问题
问题1:关联构建方法调用错误
Rails 中关联构建方法分两种场景:
belongs_to侧(Schedule 属于 Movie):用build_关联名(参数)单数形式,比如@schedule.build_movie(xxx)has_many侧(Movie 有多个 Schedule):用关联名.build(参数)复数关联名+build,你写的@movie.build_schedules()是错误写法,正确的空实例化写法是@movie.schedules.build,不需要传参数,会自动把新 Schedule 的movie_id绑定到当前 @movie 的 id 上。
问题2:控制器未获取对应的父级 Movie
你的表单提交地址是 movie_schedules_path,属于嵌套路由,路由参数里会携带 movie_id,你需要先根据这个参数找到对应的 Movie 实例,才能基于它创建关联的 Schedule。
问题3:create 方法未关联 Movie,保存必然失败
你当前的 create 方法直接用 Schedule.new(schedule_params) 实例化,没有给必填的 movie_id 赋值,数据库层面 movie_id 是非空约束,保存一定会报错。
问题4:表单字段类型和数据库字段不匹配
你的 schema 中 start_time 和 end_time 是 time 类型,只能存储时分秒,但是表单里用了 date_field 只能选日期,提交的参数会和字段类型不匹配,要么把字段改成 datetime 类型,要么把表单字段换成 time_field。
修改后的代码参考
1. 控制器修改
class SchedulesController < ApplicationController # 嵌套路由下先获取对应的 Movie before_action :find_movie, only: [:new, :create] def index @movies = Movie.joins(:schedules).select("movies.*", "schedules.*") end def new # 基于当前 Movie 实例化空的 Schedule @schedule = @movie.schedules.build end def create # 直接通过关联创建,自动赋值 movie_id @schedule = @movie.schedules.new(schedule_params) if @schedule.save redirect_to schedules_path else # 保存失败回显错误 render :new end end private def find_movie @movie = Movie.find(params[:movie_id]) end def schedule_params params.require(:schedule).permit(:start_time, :end_time) end end
2. 表单字段修改
如果确认用 time 类型存储,把字段换成 time_field:
<div class="field"> <%= form.label :start_time %> <%= form.time_field :start_time %> </div> <div class="field"> <%= form.label :end_time %> <%= form.time_field :end_time %> <%= form.submit %> </div>
如果需要同时存日期和时间,先跑迁移把字段改成 datetime 类型,再用 datetime_field 即可。
补充说明
build 方法和 new 功能完全一致,只是用于关联场景下自动绑定外键,你可以传属性参数提前赋值,比如 @movie.schedules.build(start_time: '10:00', end_time: '12:00'),不传就是空实例,和直接 Schedule.new 的区别只是自动填了 movie_id。
内容的提问来源于stack exchange,提问作者Beginner Professional
相关产品推荐
相关产品推荐

