2015-10-02 4 views
0

Я пытаюсь создать форму для подобной кнопки. Подобная модель является полиморфной для разных типов моделей (комментарии/сообщения/и т. Д.) И принадлежит определенному пользователю.Создание формы для аналогичной кнопки в полиморфных отношениях в Rails

Когда этот пользователь просматривает элемент блога, например, я хочу показать подобную кнопку под сообщением. Я мои маршруты настройки таким образом, что подобные маршруты всегда вложен внутри полиморфного объекта, для которой они предназначаются:

Таким образом, для должностей, например:

#routes.rb 
    resources :posts do 
    resources :likes, only: [:create, :destroy] 
    end 

Так пост ссылка будет Посмотреть/posts /: post_id/likes/(метод: Post)

В контроллере я создаю новый объект Like, назначаю его пользователю и сохраняю его. Это прекрасно работает.

Проблема возникает, когда я пытаюсь создать форму для удаления. Я действительно не знаю, как это создать, я знаю, что ссылка должна быть/posts /: post_id/like /: id (метод: Delete), но при ее настройке это приводит к ошибке

Я думаю, что форма могла также нужно реорганизовать, но я не знаю, как создавать формы для этих «сложных» отношений.

#shared/_like_button.html.haml 

- if not @post.is_liked_by current_user 
    = form_for(@post.likes.build, url: post_likes_path(@post)) do |f| 
    = f.submit 
- else 
    = form_for(@post.likes.find_by(user_id: current_user.id), url: post_like_path(@post), html: {method: :delete}) do |f| 
= f.submit 

EDIT:

Я думаю, что главная проблема заключается в том, что post_like_path (@post) doens't получить визуализации правильно, потому что я не знаю о: ид тому подобное. Поэтому я пытаюсь создать ссылку на ActionController :: UrlGenerationError в PostsController # при попытке создать ссылку.

+0

Можете ли вы отправить сообщение об ошибке? – RichardAE

+0

Спасибо, ответ Сандера был тем, что я искал! –

ответ

2

Это должно работать:

= form_for([@post, @post.likes.find_by(user_id: current_user.id)], html: {method: :delete}) do |f| 

url: post_like_path(@post) в вашем коде ожидает второй аргумент (like объект). Вот что выдает ошибку. Но это не актуально, если вы вложили вложенные ресурсы в массив в первом аргументе помощника form_for.

Если запись передается form_for является ресурсом, то есть оно соответствует набор RESTful маршрутов, например, с использованием метода ресурсов в config/routes.rb. В этом случае Rails просто выведет соответствующий адрес из самой записи. (источник: http://apidock.com/rails/ActionView/Helpers/FormHelper/form_for)

Вы можете передать массив ресурсов, если ваш ресурс вложен в другой ресурс.

Теперь ...Вероятно, вы захотите снова использовать этот код для своих других полиморфных моделей. Вы можете сделать это путем передачи @post или @comment на ваш частичный так:

= render :partial => 'like_button', locals: {likable: @post} 

и реорганизовать парциальное так:

= form_for([likable, likable.likes.find_by(user_id: current_user.id)], html: { method: :delete}) do |form| 
+0

Большое спасибо! Не могли бы вы объяснить, что означают множественные переменные в скобках [@post, @ post.likes]? –

+0

Когда вы вставляете маршруты, вам необходимо передать все объекты помощнику URL, которые имеют: id в самом маршруте, поэтому вы передаете массив всех объектов, определенных на маршруте, - для действия создания ему требуется только post (/ posts /: id/likes), но для удаления ему нужны как пост, так и подобный объект (/ posts /: post_id/likes /: id) – RichardAE

+0

Отлично, спасибо! Один из последних вопросов, после того, как частичные мне нужно включить некоторые частичные (и даже частично обработанные .erb частичные из обратного вызова ajax) и продолжать устанавливать одну и ту же переменную. Могу ли я установить переменную как глобальную, является первой частичной? @likeable = симпатичный? –

1

Нет необходимости использовать действительную форму, вы можете сделать это с помощью link_to. Вот пример с простой текстовой ссылкой (чтобы убедиться, что он работает)

- if not @post.is_liked_by current_user 
    = link_to 'Like', post_like_path(@post), method: :post 
- else 
    = link_to 'Delete', post_like_path([@post, @post.likes.find_by(user_id: current_user.id)]), method: :delete 

Затем вы используете кнопки/изображений в качестве самой ссылки.

- if not @post.is_liked_by current_user 
    = link_to post_like_path(@post), method: :post do 
    # some html image/button 
- else 
    = link_to post_like_path([@post, @post.likes.find_by(user_id: current_user.id)]), method: :delete do 
    # some html image/button 

Обновлен этот код с помощью принятого ответа, поэтому любой, кто ищет в будущем, может использовать link_to.

+0

Я уже пробовал что-то вроде этого, проблема в том, что я продолжаю получать: ActionController :: UrlGenerationError в PostsController # show error. Хотя ссылка появляется на моих маршрутах. Возможно потому, что: id не задан! (и мне это не нужно, потому что у меня есть вся информация, чтобы удалить подобное) –

+0

Опубликуйте эти ошибки, и мы это выясним! – RichardAE

+0

Обновлен ответ с исправлением URL-адреса Sander. – RichardAE