如何构建一个带有字符串ID而不是数字ID的link_to标记?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何构建一个带有字符串ID而不是数字ID的link_to标记?相关的知识,希望对你有一定的参考价值。
我有一个关于Rails 5的路由问题。我在config / routes.rb文件中有这个
resources :votes
我的VotesController中的“show”方法可以采用数字或字符串形式的ID。
def show
id = params[:id]
if id.present?
# If they entered a name
if id.to_i == 0
name = id.gsub "_", " "
@person = Person.find_by_name(name)
else
@person = Person.find_by_id(id)
end
我曾经能够构建这个link_to链接到方法来生成一个带有数字ID的链接...
<%= link_to person.name, vote_path(person), :class => 'unvotedPersonLink' %>
但是,我想生成一个带有ID字符串值的链接,由我的模型中名为“person.seo_name”的方法定义。所以我尝试了这个
<%= link_to person.name, vote_path(:id => person.seo_name), :class => 'unvotedPersonLink' %>
但得到了错误
No route matches {:action=>"show", :controller=>"votes", :id=>nil} missing required keys: [:id]
如何构建我的link_to标记,以便它传递我想要的“字符串”参数而不是数字参数?
你可以传递你想要的任何东西。如果错误告诉您传递的ID是nil
,那么您使用的seo_name
的Person
属性是nil
。
只要vote_path
期待一个ID,您可以通过rake routes | grep vote
查看,那么只要生成一个链接就可以正常工作:
<%= link_to person.name, vote_path(person.seo_name) %>
但请记住,它需要您在控制器中进行必要的调整,以便根据persons
列而不是seo_name
搜索id
表。
此外,我强烈建议你utilize a gem称为friendly_id
为你想要完成的。它会使事情变得更加清洁和干燥,因为您可以在任何模型中轻松使用它。只需将friendly
添加到查询中,您就可以轻松使用ID或URL友好的slug来查询表格:
Person.friendly.find(1)
# OR #
Person.friendly.find('this-is-a-url-friendly-string')
在你看来
<%= link_to person.name, vote_path(person), :class => 'unvotedPersonLink' %>
要么
<%= link_to person.name, vote_path(id: person.seo_name), :class => 'unvotedPersonLink' %>
在你的控制器中
@person = Person.find_by(id: params[:id]) || Person.find_by(name: params[:id])
确保seo_name方法没有返回nil
例外来自vote_path
,因此我们可以专注于此而不用担心link_to
或控制器。
当我遇到这样的路线问题时,我要做的第一件事就是运行rake routes
(或现在的rails routes
),以确保我有正确的名字。其次,我使用app
变量在控制台中玩游戏。例如:
> app.vote_path(1)
=> "/votes/1"
> app.vote_path(id: 1)
=> "/votes/1"
> app.vote_path("foo")
=> "/votes/foo"
> app.vote_path(id: "foo")
=> "/votes/foo"
> app.vote_path(nil)
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"votes", :id=>nil}, possible unmatched constraints: [:id]
> app.vote_path(id: nil)
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"votes", :id=>nil}, possible unmatched constraints: [:id]
你说其他地方你已经检查过person.seo_name
没有返回nil,但我会再次检查,但看起来确实是这个问题。试试这个:
p = Person.find 5 # or whatever is the numeric id
app.vote_path(p.seo_name)
参数可以包含任何信息,但您必须根据需要在控制器中处理它们。默认情况下,路由需要有一个称为:id
的参数。如果您希望在路由中使用其他名称,则可以覆盖默认资源标识符:id
确保person.seo_name
没有返回nil
。所以,你可以在before_save
模型中使用Person
回调。在那里,您可以使用特定数据设置seo_name
字段。
class Subscription < ActiveRecord::Base
before_save :populate_seo_name, on: :create
private
def populate_seo_name
self.seo_name = ...
end
end
这在过去的https://stackoverflow.com/a/26600064/4652075已被回答。
您正在将字符串传递给期望整数的字段,并将其呈现为空。您应该将字符串值传递给期望字符串的字段。如果你的“投票”模型是由ActiveRecord生成的,那么它很可能是一个整数。
在你的情况下:
class Person < ApplicationRecord
def to_param
identifier
end
# or
alias_method :to_param, :identifier
end
class VotesController < ApplicationController
before_action :set_voter
def show end;
private
def set_voter
if !params[:id]?
@person = Person.find_by(identifier: params[:seo_name])
else
@person = Person.find(params[:id])
end
end
end
# in the view
<%= link_to person.name, votes_path(identifier: person.seo_name), class: "whatever" %>
应该管用。
以上是关于如何构建一个带有字符串ID而不是数字ID的link_to标记?的主要内容,如果未能解决你的问题,请参考以下文章
为啥某些文件的组显示数字(看起来像 ID),而不是字母字符串?
使用干净的字符串 url,而不是使用带有 ui-router 的 mongo 对象 id 的 url
Rails 是不是支持带有方法 post 的 link_to?