存在?在控制台中返回true,但在我的控制器

时间:2015-08-19 20:08:02

标签: ruby-on-rails

我正在尝试创建一个按日期和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

发生了什么?

2 个答案:

答案 0 :(得分:5)

Rails有几种查找器方法,如find_or_initialize_byfind_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