我正在尝试创建一个按日期和school_id查找课程的创建操作。如果这些参数没有课程,那么我创建一个新的课程。我没有使用find_by_or_create或类似方法的原因是因为我想添加Lesson的目标(如果它存在),也不会覆盖它。
这是我的控制人员,我相信所有相关内容:
存在吗? call永远不会返回true,即使我运行rails console并使用相同的参数将其键入控制台,它也会返回true。与find_by相同def create
find_or_create_lesson
if @lesson.save
flash[:success] = "Response logged"
redirect_to @lesson
else
@user = current_user
@school_options = School.all.map { |s| [s.name, s.id] }
render 'new'
end
end
private
# strong params
def lesson_params
params.require(:lesson).permit(:school_id, :date,
goals_attributes: [:id, :user_id,
:text, :lesson_id])
end
# Finds a lesson with the same date and school, or creates the lesson
def find_or_create_lesson
search_params = { date: lesson_params[:date],
school_id: lesson_params[:school_id] }
if Lesson.exists?(search_params)
@lesson = Lesson.find_by(search_params)
@lesson.goals << Goal.new(goals)
@lesson.assign_attributes(search_params)
else
@lesson = Lesson.new(lesson_params)
end
end
发生了什么?
答案 0 :(得分:5)
Rails有几种查找器方法,如find_or_initialize_by
和find_or_create_by
,这使得处理可能会或可能不会保留的记录的情况更加简单。
@lesson = Lesson.find_or_initialize_by(
date: lesson_params[:date],
school: lesson_params[:school_id]
)
要将其集成到您的应用中,您可以:
def create
@lesson = Lesson.find_or_initialize_by(
date: lesson_params[:date],
school: lesson_params[:school_id]
)
@lesson.assign_attributes(lesson_params)
if @lesson.save
flash[:success] = "Response logged"
redirect_to @lesson
else
@user = current_user
@school_options = School.all.map { |s| [s.name, s.id] } # can be refactored out
render 'new'
end
end
private
# strong params
def lesson_params
# we only really want to assign goals_attributes
params.require(:lesson).permit(goals_attributes: [:id, :user_id,
:text, :lesson_id])
end
Rails有一个collection_select
辅助方法,它会创建一个包含集合选项的选择标记,因此无需使用School.all.map { |s| [s.name, s.id] }
手动创建选项数组。
<%= f.collection_select(:school_id, School.all, :id, :name) %>
如果您想确保在学校的同一日期无法创建两个课程,则应添加唯一性约束。
使用迁移创建数据库索引,以便数据库强制执行该规则。 (避免竞争条件)
# db/migrations/add_index_to...
class AddIndexSchoolDateIndexToLessons
def change
add_index :lessons, [:date, :school_id], unique: true
end
end
添加模型验证以提供用户反馈。
class Lesson < ActiveRecord::Base
# ...
validates : date, uniqueness: { scope: :school_id }
end
答案 1 :(得分:1)
您可以重构使用find_or_initialize_by。
def find_or_create_lesson
search_params = { date: lesson_params[:date],
school_id: lesson_params[:school_id] }
@lesson = Lesson.find_or_initialize_by(search_params)
@lesson.goals << Goals.new(goals) unless @lesson.persisted?
@lesson.save
end