【问题标题】:Helper method not triggering辅助方法未触发
【发布时间】:2020-11-23 10:05:19
【问题描述】:

我正在开发一个应用程序,您可以在其中将游戏添加到库中并删除它们。我有通过单击按钮来工作的添加功能,但是我没有显示“从库中删除”的 if 语句。

这是我的游戏控制器中控制添加/删除功能的库方法:

def library
    type = params[:type]
    game = Game.new(game_params)
    game.fetch_data

    if type == "add"
      current_user.library_additions << game
      redirect_to user_library_path(current_user), notice: "Game was added to your library"

    elsif type == "remove"
      current_user.library_additions.delete(game)
      redirect_to root_path, notice: "Game was removed from your library"
    else
      # Type missing, nothing happens
      redirect_to game_path(game), notice: "Looks like nothing happened. Try once more!"
    end

在视图中,“添加到库”按钮应该出现在您的库中没有的游戏上,如果它在您的库中,它应该切换到“从库中删除”

<% if user_added_to_library?(current_user, game) %>

            <button type="button"><%= link_to 'Remove from library', add_game_path(game.id, type: "remove", game: game), method: :put %> </button>

          <% else %>
           <button type="button"> <%= link_to 'Add to library', add_game_path(game.id, type: "add", game: game), method: :put %> </button>
          <% end %>

user_added_to_library 决定的动作?不工作,所以我总是看到“添加到库”按钮。

这是我的 user_added_to_library 助手?

module GamesHelper
  def user_added_to_library? user, game
    user.libraries.where(user: user, game: @game).any?
  end
end

我想也许我需要将库更改为 library_additions,但我收到 StatementInvalid 错误。现在编写代码的方式不会抛出错误,但它可能根本不存在。

如有必要,我的用户模型:

class User < ApplicationRecord

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  has_many :games
  has_many :libraries
  has_many :library_additions, through: :libraries, source: :game
end

我需要更改我的 user_added_to_library 吗?方法还是有其他问题?

【问题讨论】:

    标签: ruby-on-rails if-statement helper


    【解决方案1】:

    这里房间里的大象实际上是该代码的一组总体设计问题。这种设计与 RESTful 相去甚远,并且违反了 HTTP 动词的语义(PUT 不应删除资源),并且使用一个方法来执行许多不同的工作(创建和销毁资源)真的很臭。你甚至没有检查游戏是否真的被保存了。

    销毁资源应通过 DELETE 请求完成。在 Rails 中,您可以通过正确使用 HTTP 动词来创建和修改资源:

    POST    /games      # create a game
    PATCH   /games/:id  # update a game
    DELETE  /games/:id  # destroy a game
    

    大多数情况可以并且应该由resources 宏生成的standard CRUD routes 处理。如果你有关系资源,你用nested routes描述这些关系。在这种情况下,您可以选择将路由嵌套在 singular resource 中,因为您正在添加/删除当前用户的游戏。

    # generates 
    # POST     /user/games
    # DELELE   /user/games/:id
    resource :user, only: [] do
      resources :games, only: [:create, :destroy]
    end 
    

    这将由您的GamesController 中的#create#destroy 方法处理。

    第二个问题实际上是您的数据库设计和模型。如果您想创建一种设计,让用户拥有可以组织到不同库中的游戏,您可以这样做:

    class User < ApplicationRecord
      has_many :libraries
      has_many :games, through: :libraries
    end
    
    class Library < ApplicationRecord
      belongs_to :user
      has_many :library_games
      has_many :games, through: :library_games
    end 
    
    class LibraryGame < ApplicationRecord
      belongs_to :library
      belongs_to :game
      has_one :user, through: :library 
    end
    
    class Game < ApplicationRecord
      has_many :library_games
      has_many :libraries, through: :library_games
      has_many :users, through: :libraries
    end
    

    在树上设置间接关联可以通过以下方式检查用户是否有游戏:

    class User < ApplicationRecord
      has_many :libraries
      has_many :games, through: :libraries
    
      def has_game?(game)
        games.where(id: game.id).exist?
      end 
    end
    

    这确实没有任何理由应该涉及辅助方法。毕竟,您实际上只是在向用户对象提出问题。这不应该涉及将两个不同的对象传递给单独的方法。

    【讨论】:

    • 作为忠告,我想说的是,您在这里确实增加了更多的复杂性,然后您的技能可以处理。我会设置一个简单的用户 -> user_games -> 游戏解决方案,并弄清楚构建应用程序的基础知识和铁路方式,而不是深入研究。
    • 我的想法是,由于数据来自 API gem,用户没有创建、更新或删除任何我需要为库创建特定添加/删除函数的内容。但是有一个特定的 library_game 模型更有意义。我将编辑我的模型并尝试使解决方案更优雅。
    • 数据来自 API 这一事实并没有真正改变基本的设计租户。您仍在对数据进行 CRUD,在 Rails 中这意味着 REST。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 2014-02-10
    • 2015-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多