【问题标题】:Creating an ActiveRecord object from another controller - am I doing it correctly?从另一个控制器创建一个 ActiveRecord 对象 - 我做得对吗?
【发布时间】:2014-05-24 22:33:49
【问题描述】:

我正在构建一个培训网站,其中有两个模型 UserCourse,它们与第三个模型 CourseCompletions 相关联。第三种模型用于跟踪哪个用户完成了哪些课程,反之亦然。前两个模型有控制器,而第三个没有。

我实现了完成课程的功能并且它可以工作(如果用户之前没有完成该课程,则单击课程页面上的“完成课程”按钮会在 course_completion 表中插入相应的行),但我不确定关于我的实现的健壮性和安全性。这在 Course_Controller.rb 中:

为简洁起见省略了辅助方法

def complete_course
    @course = current_course
    @user = current_user
    if !already_completed
        @course.course_completions.create(user_id: @user.id, course_id: @course.id, completion_date: Time.now)
        flash[:success] = "Congratulations! Your progress has been saved."
        redirect_to course_path
    else
        flash[:success] = "Looks like you have already completed this course before, but mad props for reviewing it!"
        redirect_to course_path
    end
end

我的问题如下:

  1. 我应该像现在这样调用 create,还是 build(或 create!)更好的选择?
  2. 我应该在该函数中使用strong parameters 吗?如果是这样,在这种特殊情况下我该怎么做?

提前谢谢你。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4


    【解决方案1】:

    改变这一行:

     @course.course_completions.create(user_id: @user.id, course_id: @course.id, completion_date: Time.now)
    

     Course_completion.create(user_id: @user.id, course_id: @course.id, completion_date: Time.now)
    

    或到

      Course_completion.create(user: @user, course: @course, completion_date: Time.now)
    

    或到

    @course.course_completions.build(user: @user, completion_date: Time.now) # you can also use new instead of build, but build is preferred in this case
    

    build 只是 new 的别名,但如果您通过以下集合创建对象,仍然是首选方式:@course.course_completions.build..

    create 相当于.new + .save,它允许你一次保存一个对象。

    create! 等价于.new + .save!,与create 相同,唯一的区别是对象不保存时会抛出异常。

    在这种情况下,您不需要使用 强参数,强参数对于防止用户更新不允许的字段的表单很重要,假设您有一个包含这些字段的表单:姓名、电子邮件、密码, 在这种情况下,恶意用户可以使用 firebug 向您的表单动态添加一个字段,例如说 admin,然后他将该字段设置为 true,这是一个如果您的数据库中有一个名为 admin 的字段,则存在安全问题,因此为了防止用户设置此字段(通常不在您的表单中),我们使用强参数来仅指定我们允许的字段用户更新。

    更新:

    回答您对上述 3 个代码部分之间差异的评论:

    它们之间没有区别,但是如果您希望两者相同,则可以编写user_id: @user.iduser: @user,Rails很聪明地理解您要设置外键user_id .

    第三个只是不同的语法或变体,而不是像我们在第一个示例中所做的那样从模型Course_completion 创建一个新对象然后插入user_idcourse_id,您只需创建一个基于集合的新对象,我的意思是收集你的“course_completions”,因为你的@course has_many course_completions(你可以说@course 有一个名为 course_completions 的集合)

    要将新对象添加到 course_completions “集合”中,您只需编写 @course.course_completions.build,然后将 user_idcompletion_date 值传递给它,但是 course_id 值呢?答案是你的收藏已经基于@course (@course.course_completions),所以你不需要设置 course_id,Rails 知道。

    希望有帮助

    【讨论】:

    • 谢谢!你能解释一下你给出的三个选项之间的区别吗?
    • 查看我的更新答案,也很抱歉在此更新之前我在前两个示例中有一个小错误 Course_completions,正确的语法是 Course_completion 没有 s因为我们根据模型名称创建了一个对象 :)
    猜你喜欢
    • 1970-01-01
    • 2012-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多