【问题标题】:How to allow users to only see edit and delete link if the article is their own?如果文章是他们自己的,如何让用户只看到编辑和删除链接?
【发布时间】:2017-10-08 16:54:58
【问题描述】:

我的用户是通过 Devise 设置的。我也可以使用 CanCanCan。

我设置了一个文章模型,任何用户都可以创建文章。他们只能删除和编辑自己的文章创作。在索引上,他们可以查看所有用户创建的所有文章。当前有一个查看、编辑和删除的选项。我只希望该选项在用户拥有的文章上可见。我希望所有其他文章行都是空白的。 (当然管理员除外。) 用户可以在views/articles/index.html.erb上查看帖子

<table>
  <tr>
    <th>Title</th>
    <th>Description</th>
  </tr>

  <% @articles.each do |article| %>
    <tr>
      <td><%= article.title %></td>
      <td><%= article.description %></td>
      <td><%= link_to 'View', article_path(article) %></td>
      <td><%= link_to 'Edit', edit_article_path(article) %></td>
      <td><%= link_to 'Delete', article_path(article),
              method: :delete,
              data: { confirm: 'Are you sure?' } %></td>
    </tr>
  <% end %>
</table>

我怎样才能让用户只看到他们拥有的帖子上的编辑和删除按钮?

我试过了,但它不起作用:

<table>
  <tr>
    <th>Title</th>
    <th>Description</th>
  </tr>

  <% @articles.each do |article| %>
    <tr>
      <td><%= article.title %></td>
      <td><%= article.description %></td>
      <td><%= link_to 'View', article_path(article) %></td>
      <% if user_signed_in? && current_user.articles.exists?(@article.id) %>
      <td><%= link_to 'Edit', edit_article_path(article) %></td>
      <td><%= link_to 'Delete', article_path(article),
              method: :delete,
              data: { confirm: 'Are you sure?' } %></td>
      <% end %>
    </tr>
  <% end %>
</table>

我也试过了:

      <% if current_user && current_user.articles.exists?(@article.id) %>

这是我的文章控制器的外观:(我知道我需要让它看起来更好。)

def create
  @article = current_user.articles.build(article_params)

  if @article.save
    redirect_to @article
  else
    render 'new'
  end
end


def update
  @article = Article.find(params[:id])
  if user_signed_in? && current_user.articles.exists?(@article.id)
    if @article.update(article_params)
      redirect_to @article
    else
     render 'edit'
    end
  elsif current_user && current_user.admin_role?
    if @article.update(article_params)
      redirect_to @article
    else
     render 'edit'
    end
  else
    redirect_to @article
  end
end

def destroy
  @article = Article.find(params[:id])
  if user_signed_in? && current_user.articles.exists?(@article.id)
    @article.destroy
    redirect_to articles_path
  elsif current_user && current_user.admin_role?
    @article.destroy
    redirect_to articles_path
  else
    redirect_to articles_path
  end
end

【问题讨论】:

    标签: ruby-on-rails devise cancan


    【解决方案1】:

    由于您可以访问 Devise 提供的 current_user 助手,因此您可以将其与文章的所有者进行比较。这可以在视图中,以呈现正确的链接以执行操作:

    <% @articles.each do |article| %>
      <tr>
        <td><%= article.title %></td>
        <td><%= article.description %></td>
        <td><%= link_to 'View', article_path(article) %></td>
        <% if current_user == article.user %>
          <td><%= link_to 'Edit', edit_article_path(article) %></td>
          <td><%= link_to 'Delete', article_path(article),
                  method: :delete,
                  data: { confirm: 'Are you sure?' } %></td>
        <% end %>
      </tr>
    <% end %>
    

    您可以将此验证移至帮助程序,在 ApplicationHelper 中以在您的大多数视图中可用,例如:

    module ApplicationHelper
      def owner?(object)
        current_user == object.user 
      end
    end
    

    您传递对象,这将根据当前用户是否等于object 用户而返回真或假。视图仅更改为:

    <% if owner?(article) %>
    

    如果您想将此验证移至控制器,或者如果您想在两种情况下都使用它,那么您可以在控制器中进行相同的验证。由于 owner? 辅助方法在控制器中不可用,因此您可以在 current_user 不是文章所有者的情况下重定向回来,例如:

    def edit
      unless current_user == @article.user
        redirect_back fallback_location: root_path, notice: 'User is not owner'
      end
    end
    

    如果您想将此部分移动到before 回调,以便能够在editdestroy 方法中使用它,那么您可以将其添加为私有方法,并可以访问@ 987654331@你可以做这样的比较,那就是:

    private
    
    def owner?
      unless current_user == @article.user
        redirect_back fallback_location: root_path, notice: 'User is not owner'
      end
    end
    

    这样你只需要将它添加为before_action回调:

    before_action :owner?, only: %i[edit destroy]
    

    很可能在定义@article 变量之前。

    注意在 Rails 5 中使用redirect_back,以前的版本可能使用redirect_to :back

    【讨论】:

    • 感谢您的帮助。我目前不在电脑旁,但稍后会尝试。
    • 伟大而简单的解决方案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-02
    • 1970-01-01
    • 1970-01-01
    • 2015-03-18
    • 2022-08-10
    • 1970-01-01
    • 2019-01-14
    相关资源
    最近更新 更多