如果文章是他们自己的,如何让用户只能看到编辑和删除 link?

How to allow users to only see edit and delete link if the article is their own?

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

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

上查看 post
<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>

如何让用户只能看到他们拥有的 post 上的“编辑”和“删除”按钮?

我试过了,但没用:

<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

由于您可以访问 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

你传递对象,这个 returns true 或 false 取决于当前用户是否等于 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 方法中使用它,那么您可以将其添加为私有方法,并且可以访问 @article 你可以进行这样的比较,它将是:

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 变量之前。

注意在Rails5中使用redirect_back,之前的版本可能使用redirect_to :back.