我在rails 4中有以下帮助方法。
def is_blog_owner?(blog_id)
if current_user && blog_id
blog = Blog.find_by(id: blog_id)
roles = current_user.roles_for_blog(blog)
roles.each do |role|
if role.role == 'Blog-Owner'
true
end
end
end
end
它有一个问题,如果当前用户的角色为零,则它似乎总是返回true。
目前的工作方式是,如果当前用户具有特定博客的博客所有者角色,则返回true。
因此,如果我访问(作为用户ID 1)users/1/blogs/2
,我将看到编辑和删除,如下所示show.html.erb
如果我然后注销并以用户ID 2登录并访问users/1/blogs/2
我仍然看到编辑和删除。我不应该这样做。
所以我在设置binding.pry
之后扔了roles
,并且在用户ID 1上找到roles
用户ID为2的博客ID为nil这应该意味着我不应该看到编辑和删除按钮,但我确实......发生了什么?!
<h2><%=@blog.title%> Profile</h2>
<p class="text-muted">
Welcome to your blog porfile page. Here you can manage the blog. You can edit or
delete the specific blog.
</p>
<% if is_blog_owner?(params[:id]) %>
<hr>
<h3>Action</h3>
<p class="text-muted">You can currently do the following actions: </p>
<%= link_to "Edit", edit_user_blog_path(current_user.id, @blog.id), :class => 'btn btn-success' %> |
<%= link_to "Delete", user_blog_path(current_user.id, @blog.id),
data: { confirm: "This is permenent. Are you sure?" },
:method => :delete,
:class => 'btn btn-danger'%>
<% end %>
我应该知道我做了一个<%= is_blog_owner?(params[:id]).inspect
并且[]
返回了...... oO。它不应该返回假吗?
答案 0 :(得分:2)
这个结构对你来说是一个问题:
roles.each do |role|
if role.role == 'Blog-Owner'
true
end
end
它返回roles
的值,大概是Array
,因此总是一个真值。不会返回块内的独立true
,而不是.each
的工作方式。通常,您使用.each
来处理数组中的项目以根据每个项目进行更改或输出,或者根据每个项目执行一些副作用。返回值始终是Array
对象,与块内部的操作无关。
相反,您可以使用似乎符合您意图的方法.any?
:
roles.any? do |role|
role.role == 'Blog-Owner'
end
答案 1 :(得分:0)
你的问题是roles.each ...
返回它被调用的枚举器 - 所以基本上你的方法总是返回roles
。
要对其进行排序,请进行更改:
def is_blog_owner?(blog_id)
if current_user && blog_id
blog = Blog.find_by(id: blog_id)
roles = current_user.roles_for_blog(blog)
roles.each do |role|
if role.role == 'Blog-Owner'
return true
end
end
end
return false
end
但重写它可能会更好,以便更好地理解它所做的事情。因此,它会查看当前用户对博客所拥有的角色,如果他们中的任何一个是“博客所有者”,则返回true?
首先,最好使用一些授权流程(例如CanCan)来隔离它,但如果您坚持使用自己的方法,则可以使用.detect
简化它:
def is_blog_owner?(blog_id)
if current_user && blog_id
blog = Blog.find_by(id: blog_id)
roles = current_user.roles_for_blog(blog)
roles.detect do |role|
role.role == 'Blog-Owner'
end
end
end
返回枚举器中与块匹配的第一个元素,否则如果没有元素匹配则返回nil。