我有两种用户类型:艺术家和粉丝。我希望粉丝能够跟随艺术家。到目前为止,它们不起作用,但取消后续工作。我create
和destroy
的设置方式相同,但似乎无法让它发挥作用。在尝试create
关系时,我收到错误无法找到没有ID的艺术家。无论如何,我可以找到艺术家的ID?
以下代码:
relationships_controller.rb
class RelationshipsController < ApplicationController
before_action :authenticate_fan!
def create
@relationship = Relationship.new
@relationship.fan_id = current_fan.id
@relationship.artist_id = Artist.find(params[:id]).id #the error
if @relationship.save
redirect_to (:back)
else
redirect_to root_url
end
end
def destroy
current_fan.unfollow(Artist.find(params[:id]))
redirect_to (:back)
end
end
artists_controller.rb
def show
@artist = Artist.find(params[:id])
end
艺术家/ show.html.erb
<% if fan_signed_in? && current_fan.following?(@artist) %>
<%= button_to "unfollow", relationship_path, method: :delete, class: "submit-button" %>
<% elsif fan_signed_in? %>
<%= form_for(Relationship.new, url: relationships_path) do |f| %>
<%= f.submit "follow", class: "submit-button" %>
<% end %>
<% end %>
模型/ fan.rb
has_many :relationships, dependent: :destroy
has_many :artists, through: :relationships
belongs_to :artist
def following?(artist)
Relationship.exists? fan_id: id, artist_id: artist.id
end
def unfollow(artist)
Relationship.find_by(fan_id: id, artist_id: artist.id).destroy
end
模型/ artists.rb
has_many :relationships, dependent: :destroy
has_many :fans, through: :relationships
belongs_to :fan
的routes.rb
resources :relationships, only: [:create, :destroy]
答案 0 :(得分:7)
基本上,您需要将artist_id
发送给该操作。将您的form
更改为此。需要进行大量的重构,但这一步对您有用:
<%= form_for(Relationship.new, url: relationships_path) do |f| %>
<%= hidden_field_tag :artist_id, @artist.id %>
<%= f.submit "follow", class: "submit-button" %>
<% end %>
在控制器中,您可以像以下一样访问它:
@relationship.artist_id = Artist.find(params[:artist_id]).id
答案 1 :(得分:1)
我会考虑用嵌套路线解决这个问题:
resources :artists, shallow: true do
resources :relationships, only: [:create, :destroy]
end
这将创建这些路线以及艺术家的常规CRUD路线:
Prefix Verb URI Pattern Controller#Action
artist_relationships POST /artists/:artist_id/relationships(.:format) relationships#create
relationship DELETE /relationships/:id(.:format) relationships#destroy
请注意,我们使用shallow: true
来定义/artists/:artist_id
下的创建路由,但不包括销毁路径。
然后您可以更改表单:
<%= form_for(Relationship.new, url: artist_relationships_path(artist_id: @artist)) do |f| %>
<%= f.submit "follow", class: "submit-button" %>
<% end %>
你的控制器:
class RelationshipsController < ApplicationController
before_action :authenticate_fan!
def create
current_fan.relationships.build(artist: Artist.find(params[:artist_id]))
if @relationship.save
redirect_to(:back)
else
redirect_to root_url # makes more sense to redirect back to @artist ?
end
end
def destroy
@relationship = current_fan.relationships.find(params[:id])
@relationship.destroy
redirect_to(:back)
# or redirect back to the artist page.
# redirect_to @relationship.artist
end
end
注意我们如何重构destroy动作 - 你永远不希望有一个带有:id param的路由指向一个完全不同的资源。这只是糟糕的REST设计。如果我们知道关系的ID,我们甚至不需要知道艺术家ID。相反,ID指的是关系资源。
要创建链接以破坏您将要执行的关系:
<%= link_to 'Unfollow', relationship_path(@relationship), method: :delete %>
让我们摆脱Fan#unfollow
方法。
我们在此时可以修复Fan#following?
方法。
def following?(artist)
relationships.exists?(artist: artist)
end
通过使用关系(在ActiveRecord意义上的单词!)而不是直接查询关系模型,您可以使用预先加载来避免其他查询,而且您也不必指定风扇。