我有一个关于Rails 5的路由问题。我在config / routes.rb文件中有这个
resources :votes
" show"我的VotesController中的方法可以采用数字或字符串形式的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字符串值的链接,由我的模型中名为&#34; person.seo_name&#34;的方法定义。所以我尝试了这个
<%= 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标记,以便它传递给我想要的&#34;字符串&#34;参数而不是数字?
答案 0 :(得分:1)
你可以传递任何你想要的东西。如果错误告诉您您传递的ID为nil
,那么您使用的seo_name
的{{1}}属性为Person
。
只要nil
期待您可以通过vote_path
查看的ID,那么只要生成链接就可以了,这样就可以了:
rake routes | grep vote
但请注意,它会要求您在控制器中进行必要的调整,以便根据<%= link_to person.name, vote_path(person.seo_name) %>
列而不是persons
来搜索您的seo_name
表格。
此外,我强烈建议您utilize a gem致电id
,了解您要完成的工作。它会让事情变得更加清洁和干燥,因为您可以在任何模型中轻松使用它。您可以轻松地使用ID 或一个URL友好的slug来查询您的表格,只需将friendly_id
添加到查询中即可:
friendly
答案 1 :(得分:0)
在你看来
<%= 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
答案 2 :(得分:0)
例外来自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)
答案 3 :(得分:0)
params可以包含任何信息,但您必须根据需要在控制器中处理它们。默认情况下,路由需要有一个名为: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
答案 4 :(得分:-1)
过去已经回答过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" %>
应该工作。