ruby-on-rails - 如何在rails 6中仅更新current_user的嵌套表单属性?
问题描述
我的 rails 6 应用程序中有一个“用户”、“任务”和“评论”模型。用户模型是使用用于身份验证的设计来定义的。用户 has_many 评论和 has_many 任务和任务 has_many 评论。我有一个“任务”的嵌套表单,它接受_嵌套属性_用于“评论”。像这样的东西:
<%= form_with model: @task do |f| %>
<%= f.text_field(:name) %>
<br><br>
<%= form.fields_for :comments do |c| %>
<%= render('comment_fields', f: c) %>
<% end %>
<%= link_to_add_association('Add comment', f, :comments) %>
<%= f.submit %>
<% end %>
'_comment_fields.html.erb' 文件如下所示:
<div class="nested-fields">
<%= f.text_area(:body) %>
<%= link_to_remove_association('Remove comment', f) %>
</div>
以上两种形式只是原始代码的最小版本,我在这里使用它们仅供参考。现在,假设一个名为“user1”的用户使用数据库中的任务表单添加了一个名为“task1”的任务,并且还使用嵌套表单添加了一些评论。我想要的是,如果其他名为“user2”的用户尝试编辑任务“task1”,那么他/她应该能够使用此表单仅添加和编辑他的评论,并且只能编辑任务名称,而“user2”不应该能够编辑或删除其他人的评论,但只有他的。我们将如何为嵌套表单执行此操作。
我们可以以某种正常的形式拥有此功能,例如:
<% if @task.user.id == current_user.id %>
<%= f.text_field(:name) %>
<% end %>
上面的代码只会在当前模型的 user_id 与当前登录用户的 id 匹配时显示 text_field,但我不知道如何在 f.fields_for 中执行此操作,因为我们在嵌套形式中没有像 @task 这样的变量。
解决方案
您可以通过属性获取由表单构建器实例包装的对象object
:
<div class="nested-fields">
<%= f.text_area(:body) %>
<% if f.object.user == current_user %>
<%= link_to_remove_association('Remove comment', f) %>
<% end %>
</div>
但是,我不会真正鼓励您重新发明授权轮。Pundit或CanCanCan gem 是最流行的选择,可以避免在您的视图和控制器中传播和复制身份验证逻辑。
使用 Pundit,您可以:
class CommentPolicy < ApplicationPolicy
def destroy?
record.user == user
end
end
<div class="nested-fields">
<%= f.text_area(:body) %>
<% if policy(f.object).destroy? %>
<%= link_to_remove_association('Remove comment', f) %>
<% end %>
</div>
CanCanCan 的等价物是:
class Ability
include CanCan::Ability
def initialize(user)
can :destroy, Comment, user: user
end
end
<div class="nested-fields">
<%= f.text_area(:body) %>
<% if can?(:destroy, f.object) %>
<%= link_to_remove_association('Remove comment', f) %>
<% end %>
</div>
推荐阅读
- reactjs - 如何在 cypress 测试中公开/访问像 Redux 这样的数据存储?
- haskell - 编译到 LLVM IR 的 Haskell 程序缺少 main
- java - com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:'OPTION SQL_SELECT_LIMIT=DEFAULT' 附近的 SQL 语法有错误
- c++ - 迭代 unordered_map 时的 std::move(key)
? - audio - 采样率可靠吗?
- python - 如何使用 Python 点击并提交数据
- swift - 如何最好地在 SpriteKit 中编写 Undo 函数?
- jquery - 使用动态和静态输入php序列化并插入到mysql表单
- reactjs - 将 redux thunk 操作链接在一起
- android - 使用存储在 Firebase 数据库中的位置在谷歌地图上自定义绘图