我正在建立一个培训网站,其中有两个模型User
和Course
,它们与第三个模型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
我的问题如下:
提前谢谢。
答案 0 :(得分:6)
更改此行:
@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
相同,唯一的区别是如果对象无法保存则抛出异常。< / p>
在这种情况下,您不需要使用强参数,强大的参数对于表单非常重要,以防止用户更新不允许的字段,假设您有一个包含以下字段的表单:名称,电子邮件,密码在这种情况下,恶意用户可以使用firebug动态地向您的表单添加字段,例如让 admin ,然后将字段设置为true,这是一个安全问题如果您的数据库中有一个名为 admin 的字段,那么为了防止用户设置此字段(通常不在您的表单中),我们使用强参数来仅指定我们允许的字段用户更新。
更新:
回答您对上述3个代码部分之间差异的评论:
它们之间没有区别,但是如果你想要的两个是相同的,要么你写user_id: @user.id
或user: @user
,Rails很聪明地理解你要设置外键是user_id
。
第三种只是一种不同的语法或变体,而不是从模型Course_completion
创建一个新对象,然后像我们在第一个例子中那样插入user_id
和course_id
,你只需要根据一个集合创建一个新对象,我的意思是收集你的“course_completions”,因为你的@course
has_many course_completions
(你可以说@course有一个名为course_completions的集合
要向您的course_completions“集合”添加一个新对象,您只需要编写@course.course_completions.build
,然后将user_id
和completion_date
值传递给它,但是course_id值呢?答案是你的收藏已经基于@course( @ course.course_completions ),所以你不需要设置course_id,Rails知道它。
希望这个帮助