link_to 主对象如何在视图中看起来更干净?
How can link_to a master object look cleaner in the view?
我有用户模型,它有很多细节。
在详细列表(索引)页面 (./details) 中有一个 link_to 返回主 table,或拥有详细信息的用户 (./user/1)。
基本上,我想知道是否有一种方法可以使 link_to 方法的语法看起来更清晰,但我不是 ruby 或 rails 约定意识到。
<% @details.each do |detail| %>
<tr>
<td><%= detail.name %></td>
<td><%= link_to User.find_by_id(detail.foreign_key_id).name, \
User.find_by_id(detail.foreign_key_id) %></td>
...
这很好用,但我似乎记得在某个时候看到过更简洁的语法。
[编辑]
同样在这种情况下,我有两种方法可以将用户关联到详细信息。
我想到的数据模型类似于项目,所以我将以这种方式呈现问题。所以一个用户可以是项目的所有者,and/or,项目的发起人。
因此,用户 class 将具有以下....
class User < ActiveRecord::Base
has_many :owned_projects, class_name: "Project", foreign_key: :owner_id
has_many :sponsored_projects, class_name: "Project", foreign_key: :sponsor_id
end
然后项目 class 将在其定义中包含此内容
class Project < ActiveRecord::Base
belongs_to :owner, :foreign_key => :owner_id, :class_name => "User"
belongs_to :sponsor, :foreign_key => :sponsor_id, :class_name => "User"
end
项目 table 有一个 owner_id 字段和一个 sponsor_id 字段,所以 User class 可以两次链接到 Project table.
考虑到所有这些,回到手头的问题,我不知道如何使用 @Michael Gaskill
描述的更清晰的语法
如果是那样的话,会是这样吗?%= link_to @project.sponsor.name, project.sponsor_id %></td>
Rails magic 好像没弄清楚,或者我配置错了。
我已经测试了 following out,正如我之前提到的,这会起作用,但我正在努力确保没有更清洁的方法。
(目标是查看有关详细信息的页面,或本示例中的 Project,并查看 User 的两个类别与它相关联,并让他们的名字成为指向他们 显示 页面配置文件的可点击链接)
<p>
<strong>Name:</strong>
<%= @project.name %>
</p>
<p>
<strong>Owner:</strong>
<%= link_to User.find_by_id(@project.owner_id).name, User.find_by_id(@project.owner_id) %>
</p>
<p>
<strong>Sponsor:</strong>
<%= link_to User.find_by_id(@project.sponsor_id).name, User.find_by_id(@project.sponsor_id) %>
</p>
如果你的关系设置正确,你应该能够做这样的事情:
%= link_to detail.user.name, detail.user %></td>
如果可能的话,您想避免在视图中执行任何 ActiveRecord 查询。如果您确实必须在视图中进行查询,请确保您没有重复它们。视图中的查询往往会导致 N+1 问题,重复它们可能会导致该问题变成 2*(N+1) 或更糟。
根据您问题中显示的新关系,您应该能够使用它来代替您的视图代码:
<p>
<strong>Name:</strong>
<%= @project.name %>
</p>
<p>
<strong>Owner:</strong>
<%= link_to @project.owner.name, @project.owner) %>
</p>
<p>
<strong>Sponsor:</strong>
<%= link_to @project.sponsor.name, @project.sponsor) %>
</p>
简而言之,Rails 魔术知道如何遍历关系以从每个赞助商和所有者模型对象中检索名称。同样,link_to
知道如何自动从发起人和所有者那里检索路径信息(作为 link_to
的第二个参数)为每个对象创建正确的 link。请注意,这在您使用模型对象(例如 "owner")而不是 object_id(例如 "owner_id")时有效。
link_to API documentation 提供了一些关于如何将 link_to
用于模型数据的更深入的指导。示例 #2 演示了此答案使用的确切技术;但是,我们选择直接从 ActiveRecord 模型(作为所有者或赞助商名称)提供 link 文本,而不是像示例中那样对其进行硬编码。
您还可以通过使用路线助手来定义您要使用的路径,从而更明确地说明您想 link 到哪条路线。让我们制作一个类似的视图页面,展示如何 link 到项目所有者和发起人的编辑页面:
<p>
<strong>Name:</strong>
<%= @project.name %>
</p>
<p>
<strong>Owner:</strong>
<%= link_to @project.owner.name, edit_owner_path(@project.owner) %>
</p>
<p>
<strong>Sponsor:</strong>
<%= link_to @project.sponsor.name, edit_owner_path(@project.sponsor) %>
</p>
您可以使用 Rails 为您创建的任何路线助手来导航到您模型的任何操作。要找出哪些路由助手可用于您的项目,您可以从命令行 运行 rake routes
,并查看如下结果:
Prefix Verb URI Pattern Controller#Action
projects GET /projects(.:format) projects#index
POST /projects(.:format) projects#create
new_project GET /projects/new(.:format) projects#new
edit_project GET /projects/:id/edit(.:format) projects#edit
project GET /projects/:id(.:format) projects#show
PATCH /projects/:id(.:format) projects#update
PUT /projects/:id(.:format) projects#update
DELETE /projects/:id(.:format) projects#destroy
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
这是通过在您的 config/routes.rb
:
中定义这些定义而定义的一组标准路由
resources :project
resources :user
在 rake routes
的输出中,您会看到左侧 "Prefix" 列中显示的路由助手。这些是您将用于向 link_to
提供显式页面 link 的标识符。它们被称为 "prefix",因为它们与 "path" 或 "url" 一起使用,分别生成相对路径或绝对路径 url。考虑这些用途:
user_path(@project.owner) # ==> "/user/9"
user_url(@project.sponsor) # ==> "http://example.com/user/23"
new_user_path # ==> "/user/new"
new_user_url # ==> "http://example.com/user/new"
请注意,其中一些路由助手必须指定一个参数,而有些则不需要。您可以从 rake routes
输出中读取此内容,因为参数是按照替换参数(例如 :id)出现的顺序提供的,不包括可选的替换参数(例如 (.:format))。资源的标准路由集为您提供了这些可以使用的路由助手:
users_path # ==> "/user"
new_user_path # ==> "/user/new"
user_path(@user) # ==> "/user/139"
edit_user_path(@user) # ==> "/user/139/edit"
其他默认路由通常不会在您的项目中直接使用,因此您不会直接引用它们。
因此,只要您拥有模型对象,就可以使用隐式路径方法创建任何要使用的 link:
<%= link_to @user.name, @user %>
或路径助手方法:
<%= link_to @user.name, user_path(@user) %>
这两个应该为用户 #69,"Scott Tenorman":
产生相同的 links
<a href="/user/69">Scott Tenorman</a>
这就是魔法的全部。这根本不是真正的魔法,而是一系列巧妙的、精心设计的约定,这些约定共同作用,使简单的事情变得容易。一旦你知道它们是如何工作的。快乐 linking!
我有用户模型,它有很多细节。
在详细列表(索引)页面 (./details) 中有一个 link_to 返回主 table,或拥有详细信息的用户 (./user/1)。
基本上,我想知道是否有一种方法可以使 link_to 方法的语法看起来更清晰,但我不是 ruby 或 rails 约定意识到。
<% @details.each do |detail| %>
<tr>
<td><%= detail.name %></td>
<td><%= link_to User.find_by_id(detail.foreign_key_id).name, \
User.find_by_id(detail.foreign_key_id) %></td>
...
这很好用,但我似乎记得在某个时候看到过更简洁的语法。
[编辑] 同样在这种情况下,我有两种方法可以将用户关联到详细信息。
我想到的数据模型类似于项目,所以我将以这种方式呈现问题。所以一个用户可以是项目的所有者,and/or,项目的发起人。
因此,用户 class 将具有以下....
class User < ActiveRecord::Base
has_many :owned_projects, class_name: "Project", foreign_key: :owner_id
has_many :sponsored_projects, class_name: "Project", foreign_key: :sponsor_id
end
然后项目 class 将在其定义中包含此内容
class Project < ActiveRecord::Base
belongs_to :owner, :foreign_key => :owner_id, :class_name => "User"
belongs_to :sponsor, :foreign_key => :sponsor_id, :class_name => "User"
end
项目 table 有一个 owner_id 字段和一个 sponsor_id 字段,所以 User class 可以两次链接到 Project table.
考虑到所有这些,回到手头的问题,我不知道如何使用 @Michael Gaskill
描述的更清晰的语法如果是那样的话,会是这样吗?%= link_to @project.sponsor.name, project.sponsor_id %></td>
Rails magic 好像没弄清楚,或者我配置错了。
我已经测试了 following out,正如我之前提到的,这会起作用,但我正在努力确保没有更清洁的方法。
(目标是查看有关详细信息的页面,或本示例中的 Project,并查看 User 的两个类别与它相关联,并让他们的名字成为指向他们 显示 页面配置文件的可点击链接)
<p>
<strong>Name:</strong>
<%= @project.name %>
</p>
<p>
<strong>Owner:</strong>
<%= link_to User.find_by_id(@project.owner_id).name, User.find_by_id(@project.owner_id) %>
</p>
<p>
<strong>Sponsor:</strong>
<%= link_to User.find_by_id(@project.sponsor_id).name, User.find_by_id(@project.sponsor_id) %>
</p>
如果你的关系设置正确,你应该能够做这样的事情:
%= link_to detail.user.name, detail.user %></td>
如果可能的话,您想避免在视图中执行任何 ActiveRecord 查询。如果您确实必须在视图中进行查询,请确保您没有重复它们。视图中的查询往往会导致 N+1 问题,重复它们可能会导致该问题变成 2*(N+1) 或更糟。
根据您问题中显示的新关系,您应该能够使用它来代替您的视图代码:
<p>
<strong>Name:</strong>
<%= @project.name %>
</p>
<p>
<strong>Owner:</strong>
<%= link_to @project.owner.name, @project.owner) %>
</p>
<p>
<strong>Sponsor:</strong>
<%= link_to @project.sponsor.name, @project.sponsor) %>
</p>
简而言之,Rails 魔术知道如何遍历关系以从每个赞助商和所有者模型对象中检索名称。同样,link_to
知道如何自动从发起人和所有者那里检索路径信息(作为 link_to
的第二个参数)为每个对象创建正确的 link。请注意,这在您使用模型对象(例如 "owner")而不是 object_id(例如 "owner_id")时有效。
link_to API documentation 提供了一些关于如何将 link_to
用于模型数据的更深入的指导。示例 #2 演示了此答案使用的确切技术;但是,我们选择直接从 ActiveRecord 模型(作为所有者或赞助商名称)提供 link 文本,而不是像示例中那样对其进行硬编码。
您还可以通过使用路线助手来定义您要使用的路径,从而更明确地说明您想 link 到哪条路线。让我们制作一个类似的视图页面,展示如何 link 到项目所有者和发起人的编辑页面:
<p>
<strong>Name:</strong>
<%= @project.name %>
</p>
<p>
<strong>Owner:</strong>
<%= link_to @project.owner.name, edit_owner_path(@project.owner) %>
</p>
<p>
<strong>Sponsor:</strong>
<%= link_to @project.sponsor.name, edit_owner_path(@project.sponsor) %>
</p>
您可以使用 Rails 为您创建的任何路线助手来导航到您模型的任何操作。要找出哪些路由助手可用于您的项目,您可以从命令行 运行 rake routes
,并查看如下结果:
Prefix Verb URI Pattern Controller#Action
projects GET /projects(.:format) projects#index
POST /projects(.:format) projects#create
new_project GET /projects/new(.:format) projects#new
edit_project GET /projects/:id/edit(.:format) projects#edit
project GET /projects/:id(.:format) projects#show
PATCH /projects/:id(.:format) projects#update
PUT /projects/:id(.:format) projects#update
DELETE /projects/:id(.:format) projects#destroy
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
这是通过在您的 config/routes.rb
:
resources :project
resources :user
在 rake routes
的输出中,您会看到左侧 "Prefix" 列中显示的路由助手。这些是您将用于向 link_to
提供显式页面 link 的标识符。它们被称为 "prefix",因为它们与 "path" 或 "url" 一起使用,分别生成相对路径或绝对路径 url。考虑这些用途:
user_path(@project.owner) # ==> "/user/9"
user_url(@project.sponsor) # ==> "http://example.com/user/23"
new_user_path # ==> "/user/new"
new_user_url # ==> "http://example.com/user/new"
请注意,其中一些路由助手必须指定一个参数,而有些则不需要。您可以从 rake routes
输出中读取此内容,因为参数是按照替换参数(例如 :id)出现的顺序提供的,不包括可选的替换参数(例如 (.:format))。资源的标准路由集为您提供了这些可以使用的路由助手:
users_path # ==> "/user"
new_user_path # ==> "/user/new"
user_path(@user) # ==> "/user/139"
edit_user_path(@user) # ==> "/user/139/edit"
其他默认路由通常不会在您的项目中直接使用,因此您不会直接引用它们。
因此,只要您拥有模型对象,就可以使用隐式路径方法创建任何要使用的 link:
<%= link_to @user.name, @user %>
或路径助手方法:
<%= link_to @user.name, user_path(@user) %>
这两个应该为用户 #69,"Scott Tenorman":
产生相同的 links<a href="/user/69">Scott Tenorman</a>
这就是魔法的全部。这根本不是真正的魔法,而是一系列巧妙的、精心设计的约定,这些约定共同作用,使简单的事情变得容易。一旦你知道它们是如何工作的。快乐 linking!