Неопределенный метод link_to_edit с использованием декоратора Draper
У меня есть модели User и Post, которые классически связаны друг с другом - User has_many :posts
а также Post 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#edit
а также posts#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 %>
вместо этого условного беспорядка он просто возвращает мне следующую ошибку:
Что я делаю неправильно?
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