【问题标题】:Correct Routing for :has_many :through正确路由 :has_many :through
【发布时间】:2017-12-09 08:53:31
【问题描述】:

好吧.. 我的导航栏中有一个带有多个下拉菜单的网站。有点像这样:

Gran Turismo(第一个标题下拉到:)

  • PS4
  • PS3 等

Forza(第二个标题下拉到:)

  • PS4
  • PS3 等..

我的目标是当我点击其中一个下拉菜单时,它会使用路线显示一个显示页面:

www.mysite.com/forza/ps4

每个人都告诉我应该将has_many :through 用于我称为平台的第三个模型。

因此我的模型是这样的:

class Game < ApplicationRecord
  has_many :platforms
  has_many :consoles, through: :platforms
end

class Console < ApplicationRecord
  has_many :platforms
  has_many :games, through: :platforms
end

class Platform < ApplicationRecord
  belongs_to :game
  belongs_to :console
end

我的路线是这样的:

  resources :platforms, only: [:show] do
    resources :games do
      resources :consoles
    end
  end

理想情况下,在我猜是平台展示的最终 show.html.erb 上,我想在平台 PS4 上展示我专门为游戏 Forza 销售的产品,我选择了我选择的下拉菜单我的选择..

但是我的路线是这样出现的:

/platforms/:platform_id/games/:game_id/consoles/:id(.:format)   

任何想法我哪里出错了?如果有更简单的方法解决这个问题?

非常感谢!

更新:

“平台”可能会有些混乱。也许“MarketPlace”会更合适。虽然现在读完了,但也许我不应该有第三个模型,而只是在控制台结束它。

如果选择了不同的游戏,我只是希望最终显示页面略有不同。

【问题讨论】:

  • 你希望你的下拉菜单是什么
  • 在我看来,您真正需要的只是一条路线,例如:/platforms/:id;但相反,您想将此路线“别名”为/:game_name/:console_name。这是possible,但很难做到正确。如果您使用更容易匹配的路线怎么办 - 例如/platform?game_name=&lt;...&gt;&amp;console_name=&lt;...&gt;?这仍然违反 Rails 约定,但更容易构建。
  • PS4 是一个控制台,而 Forza 是一个游戏。平台的名称是什么?
  • @Pavan 我可以看到模型的用途,但命名令人困惑。也许像GameRelease 这样的东西更好? name 可以是 "Forza for PS4"

标签: ruby-on-rails ruby controller routes associations


【解决方案1】:

您可以使用自定义路由获得您想要的确切路由(例如www.mysite.com/forza/ps4),如下所示:

get "/:game/:console", to: "games#show"

GamesController 中,您可以检索这两个参数并搜索您要显示的Game,如下所示:

def show
  @console = Console.find_by(name: params[:console])
  @game    = Game.find_by(name: params[:game])
  # ...
end

请记住,只有满足以下所有条件,这才会始终如一地工作:

  • Game 模型包含唯一名称(或您选择用作slug的任何列)。

  • 您没有其他具有相同模式的路线(例如 /:other/:route)。

  • Game 名称与任何模型名称不同(除非该模型具有处理冲突的自定义路由,或者根本没有路由)。

  • 路线定义在路线的末尾,因此它不会干扰其他路线。

【讨论】:

  • 另请注意:正如我在上面的 cmets 中所避免的那样,这种路由方法“容易出错”,因为如果您不小心,可能会发生冲突。 Rails 提供 RESTful 路由(例如 /platorms/:id)而不是这个是有充分理由的……例如,如果您有两个“平台”/“游戏版本”用于相同的游戏名称和控制台——例如“限量版”发布?这条路线会发生冲突。
  • @TomLord 你是对的,这种方法必须小心使用。关于可能与两个“平台”/“游戏发布” 的冲突,这应该不是问题,因为此答案仅考虑 GameConsole 模型(因为 OP 的最后一次编辑)。因此,只要 GameConsole 具有唯一的名称,这应该可以工作。
  • 是的,同意...但是 (1) 游戏名称是唯一的吗? (原始帖子从未澄清过这一点。)并且(2)是否有任何 other 像这样的非 RESTful 路由,这可能会导致冲突? (原帖从未显示完整的routes.rb。)如果有一个名为foo 的游戏和一个名为Foo 的模型,您甚至可能会遇到路线冲突!
  • @TomLord 没有想过模型可以被命名为游戏的边缘情况,这将是一个问题(关于 12 i> 我 假定 唯一的名称,没有其他类似的路线)。感谢您的 cmets,我将添加一些注释以澄清何时可以使用。
  • 谢谢大家!这正是我所需要的,因为只有少数“游戏”而且它们的名称都不同(也没有特别版!):) 我确实有一个最后一个问题,在 Show 下的游戏控制器中:名称向我显示了一个错误“未定义的方法'名称'”,但是如果我输入 id: 并更改它的 url 它工作正常。这可能是在我的 ActiveRecords 中使用大写字母的问题,所以当我以小写形式调用它时行不通?还是有什么不同?打扰各位了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-04
  • 2016-01-20
  • 2014-09-01
相关资源
最近更新 更多