【问题标题】:Routing in Rails has problems with Controller/action/id routeRails 中的路由存在 Controller/action/id 路由问题
【发布时间】:2015-08-10 23:08:10
【问题描述】:

在我的 Rails 4 应用程序中,我通过 PagesController 创建页面以形成菜单。该菜单具有指向相应控制器的 redirect_to 索引操作的链接。该页面模型的列是:id,:title,:access_level,:html(实际上是指控制器),:icon

示例数据为:5、Employees、3、employees、users

注意:代码的不相关部分,例如“resources :employees”是不可见的!

路线文件:

resources :pages
resources :access

页面控制器:

def show
  @pages = Page.find(params[:id])
  redirect_to controller: "#{@page.html}", action: "index"
end

阻止生成链接

<% @pages = Page.all %>
<% @pages.each do |page| %>
<li>
    <%= link_to({ controller: "pages", action: "show", id: "#{page.id}" }) do %><i class="fa fa-<%= page.icon %> fa-fw"></i> <%= page.title %>
    <% end %>
</li>
<% end %>

基于示例的HTML生成的link_to:

<a href="/pages/5"><i class="fa fa-users fa-fw"></i> Employees</a>

一切正常,除非我尝试实现基本登录系统但收到以下错误:

ActionController::UrlGenerationError in Access#index
Showing C:/Users/Samsung/Documents/rails/AjansTakip/app/views/access/index.html.erb where line #9 raised:

No route matches {:action=>"attempt_login", :controller=>"access"}

Index.html.erb Access 视图的第 9 行

<%= form_for :access, url: {action: "attempt_login"} do |f| %>

AccessController(:id_number 是 Identification_number 的缩写,与 :id 无关)

def attempt_login
    if params[:id_number].present? && params[:password].present?
        found_user = Employee.where(id_number: params[:id_number]).first
        if found_user
            authorized_user = found_user.authenticate(params[:password])
        end
    end
    if authorized_user
        redirect_to controller: 'pages', action: 'index'
    else
        redirect_to action: 'login'
    end
  end

我正在关注 Lynda Rails 4 基本培训,但我无法通过基本登录系统实施的第一部分,因此请不要评论除路由之外的任何编码部分,因为我正在尝试在我的拥有。

就解决方案而言,我尝试了这个解决方案,它可以将错误传递给另一个解决方案

get 'access/attempt_login', to: 'access#attempt_login'

但我很确定有更好的方法来处理这些情况。 当我通过 index.html.erb 上的帖子提交表单时出现另一个错误:

No route matches [POST] "/access/attempt_login"

我认为问题的出现是因为默认路由是 :controller(/:id(/:action)) 并且控制器在 :action 之前需要一个 :id。对于不需要 :id 的所有类型的操作,我认为路由“获取”没有意义。

我使用的另一个解决方案是将默认路由更改为“:controller(/:action(/:id))”,但这会导致比它解决的问题更多的问题(我们甚至可以说它根本没有解决任何问题)。甚至菜单中的链接也会中断,因为 link_to :action "show" 不会被解析为 href="pages/show/5"。我还尝试将链接生成为 link_to({ controller: "pages", action: "show", id: "show/#{page.id}" }) 但这并不实用和动态就像我想成为的那样。

请指点我正确的方向。我也愿意更改 Paging 与 PagesController 的工作方式,我想不出更好的方法将页面存储在数据库中并将它们全部重定向到一个地方。

谢谢

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 routes


    【解决方案1】:

    是的,不要使用默认控制器的东西,那是老派。相反,试试这个:

    删除获取行:

    get 'access#attempt_login', to: 'access#attempt_login'
    

    现在,既然您希望将它放在资源集合中,请尝试以下操作:

    resources :access do
      collection do
        get :attempt_login
      end
    end
    

    然后以你的形式:

     <%= form_tag attempt_login_access_path, method: :get do |f| %>
    

    当涉及到不用于创建或更新操作的 url 时,我使用 form_tag。当您有模型时,Form_for 很好。 get 方法也很重要,因为表单默认为 post。您可能需要仔细检查该路由路径:

    bundle exec rake routes | grep attempt
    

    并确保方法正确。

    【讨论】:

    • 按照您的建议进行操作,正确的路径是尝试登录访问索引路径,因此我能够解决问题。你介意我让你剖析“attempt_login_access_index_path”并解释为什么“index”在那里吗?它是视图的名称吗?为什么它没有像您预见的那样生成路径?谢谢。
    • 关于索引的好问题。为了更好地解释它,当您添加一个集合块时,您放入其中的任何方法都将映射到该控制器,该操作。因此,我们正在对 attempt_login 操作进行获取请求。如果您使用member 而不是collection,它会做同样的事情,但需要一个id:/access/:id/attemp_login,因此您可以对单一资源执行额外的方法。我做了类似的设置,但我没有得到索引的东西:)。如果您想发布完整的路线文件,我可以尝试弄清楚。
    • 在遇到这种情况时,路由文件只有简单的非嵌套资源,例如资源 :employees、:projects 等。感谢您的努力 :)
    猜你喜欢
    • 1970-01-01
    • 2020-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多