使用Draper装饰器的未定义方法link_to_edit

时间:2017-01-26 10:53:41

标签: ruby-on-rails draper

我有一个User和Post模型,它们以经典的方式相互关联 - User has_many :postsPost belongs_to :user。在我显示用户个人资料的users#show中,我还列出了他所做的所有帖子。此外,我希望有链接来尊重地编辑和删除每个帖子。所以,我用这个来弥补:

<% @user.posts.each do |post| %>
  <h1><%= link_to post.title, post_path(post) %></h1>
  <% if @user == current_user %>
      <%= link_to 'Edit', edit_post_path(post) %>
      <%= link_to 'Delete', post_path(post), method: :delete %>
  <% end %>
<% end %>

但是肯定将这个逻辑置于视图中导致一团糟,所以我决定使用Draper并为此编写装饰器。在我们检查posts#editposts#delete方法的权限时,我想出了Post模型的装饰器并尝试在PostsController中使用它。在这里:

class PostDecorator << Draper::Decorator
  delegate_all

  def link_to_edit
    if object.user == current_user
      h.link_to 'Edit', h.edit_post_path(object)
    end
  end

  def link_to_delete
    if object.user == current.user
      h.link_to 'Delete', h.post_path(object), method: :delete
    end
  end   
end

然后,在我的PostsController

# ... class definition
before_action :set_post, only: [:show, :edit, :update, :destroy]

# ... other controller methods
def edit; end

def update
  if @post.update(post_params)
    @post.save
    redirect_to post_path(@post)
  else
    render 'edit'
  end
end

def destroy
  @post.destroy
  redirect_to feed_path
end

private

# Using FriendlyId gem to have neat slugs
def set_post
  @post = Post.friendly.find(params[:id]).decorate
end

但是每当我尝试使用我的新助手<%= post.link_to_delete %><%= post.link_to_edit %>而不是那个有条件的混乱来渲染我的用户个人资料以及他的帖子列表时,它只会返回以下错误:

error

我做错了什么?

1 个答案:

答案 0 :(得分:1)

你可能在此期间想到这一点,但这是其他人的答案:你在控制器中调用了@post = ....decorate但你在视图中使用了@user.posts.each { |post| ... }。送入该块的对象未进行装饰。只有@post

在您看来,您应该做过像@user.posts.each { |raw_post| post = raw_post.decorate }之类的事情。显然,有了ERB语法。或@user.decorated_posts.each ...其中

class User < ActiveRecord::Base
  ...
  def decorated_posts
    # this will load every post associated with the user.
    # if there are a lot of them you might want to only load a limited scope of them
    posts.map(&:decorate)
  end
  ...
end