无法找到没有ID的用户,rails 4

时间:2015-07-19 18:38:25

标签: ruby-on-rails ruby-on-rails-4

我有两种用户类型:艺术家和粉丝。我希望粉丝能够跟随艺术家。到目前为止,它们不起作用,但取消后续工作。我createdestroy的设置方式相同,但似乎无法让它发挥作用。在尝试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]

2 个答案:

答案 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意义上的单词!)而不是直接查询关系模型,您可以使用预先加载来避免其他查询,而且您也不必指定风扇。