不同模型中对象的链接路径

问题描述 投票:0回答:3

我正在创建一个包含两组嵌套模型的 Rails 应用程序:

目标 -> 阶段 -> 模板

联系人 -> 跟踪器 -> 电子邮件

在我的目标的显示页面上,我可以列出与该目标相关的所有跟踪器并显示标题等信息,但我不知道如何链接到跟踪器。

我已经尝试了 link_to 的许多变体,但似乎没有任何效果,所以我真的很感激一些帮助。非常感谢!

配置Routes.rb:

Rails.application.routes.draw do
  get 'pages/inbox'
  get 'pages/trackers'
  devise_for :users

  resources :contacts do
    resources :trackers do
      resources :emails
    end
  end
  resources :goals do
      resources :stages do
        resources :templates
      end
  end
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Defines the root path route ("/")
 root "contacts#index"
end

我的目标控制器:

  def show
    @trackers = Tracker.all
    @tracker = Tracker.all
  end

我的目标模型:

class Goal < ApplicationRecord
  has_many :stages , dependent: :destroy
  has_many :trackers
end

我的追踪器型号:

class Tracker < ApplicationRecord
  belongs_to :contact
  belongs_to :goal
  belongs_to :stage
  has_many :emails , dependent: :destroy
end

这是 Goal 的 Show.html.erb 页面,其中包含错误的链接到 Tracker 的代码:

    <% for tracker in @goal.trackers %>
      <hr></hr>
            <%= link_to goal_tracker_path(@goal, tracker) do %> #Doesn't work
            <p><%= tracker.title %> | <%= tracker.contact.first_name %></p>
        <% end %>
     <% end %>
ruby-on-rails model-view-controller model hyperlink
3个回答
0
投票

tracker
资源没有嵌套到
goal
,而是嵌套到
contacts
。路径
goal_tracker_path (eg: /goals/1/trackers/1)
不存在。只有
contact_tracker_path
存在。如果你运行
rails routes
.

,你可以看到这个

有几种方法可以解决这个问题。

  • 取消嵌套。但这不会有嵌套的 url 结构。路径将是
    /trackers/id
    。的链接看起来像
link_to 'Title', tracker
  • Nest tracker 资源也指向目标。在这种情况下,
    goal_tracker_path
    contact_tracker_path
    都将可用,尽管两者都将使用相同的
    TrackersController
    。如果需要,您总是可以编写另一个控制器并在路由中指定它。路线看起来像
resources :contacts do
    resources :trackers do
      resources :emails
    end
  end
  resources :goals do
      resources :trackers
      resources :stages do
        resources :templates
      end
  end
  • 或者您可以将跟踪器资源移动到目标资源,除非您也需要
    contact_tracker_path

最好总是看一下

rails routes
以确保路径存在。


0
投票

跟踪器嵌套在合约下方。因此,你需要将跟踪器所属的合约也传递给

link_to
方法:

<% @goal.trackers.each do |tracker| %>
  <hr />
  <%= link_to goal_tracker_path(tracker.contact, tracker) do %>            
    <p><%= tracker.title %> | <%= tracker.contact.first_name %></p>
  <% end %>
<% end %>

或者你可能想考虑不要在你的路由中使用太多的嵌套。官方 Rails 指南建议使用 Shallow Nesting 而不是嵌套路由。


0
投票

您实际上没有在

trackers
中嵌套
goals
资源的主要问题。

为此,您需要:

resources :contacts do
  resources :trackers
  # ...
end

resources :goals do
  resources :trackers
  # ...
end

这里

/contacts/1/trackers
/goals/1/trackers
都会去
TrackersContoller#index
方法。一种常见的处理方式是我所说的“参数嗅探法”:

class TrackersContoller
  # GET /contacts/1/trackers
  # GET /goals/1/trackers
  # GET /trackers
  def index
    if params[:contact_id].present?
      @trackers = Contact.find(params[:contact_id]).trackers
    elsif params[:goal_id].present?
      @trackers = Goal.find(params[:contact_id]).trackers
    else
      @trackers = Tracker.all
    end
  end
 
  # ...
end

就单一职责原则而言,这真是太臭了,因为控制器现在正在处理 RESTful 资源的三种不同变体。

我通常更喜欢将资源的嵌套表示路由到它们自己的控制器:

resources :trackers # TrackerController

resources :contacts do
  # routes to Contacts::TrackerContoller
  resources :trackers, only: [:new, :create, :index], 
                       module: :contacts
  # ...
end

resources :goals do
  # routes to Goals::TrackerContoller
  resources :trackers, only: [:new, :create, :index], 
                       module: :contacts
  # ...
end
module Contacts
  # Creates and lists trackers belonging to a Contact
  class TrackersContoller < ApplicationController
    # GET /contacts/1/trackers
    def index
      Contact.find(params[:contact_id]).trackers
    end
  end
end
module Goals
  # Creates and lists trackers belonging to a Goal
  class TrackersContoller < ApplicationController
    # GET /goals/1/trackers
    def index
      Goal.find(params[:goal_id]).trackers
    end
  end
end

同样,在你疯狂地构建一个俄罗斯套娃方案之前,你可能应该阅读 Jamis Buck 的关于为什么深度嵌套是一件坏事的经典文章

经验法则:资源的嵌套永远不应超过 1 层 深的。集合可能需要由其父级确定范围,但特定的 成员总是可以通过 id 直接访问,不需要 范围(除非 id 不是唯一的,出于某种原因)。

代码可能已经过时了,但基本原则与 15 年前一样重要。这也是 Rails 指南推荐的。

© www.soinside.com 2019 - 2024. All rights reserved.