Rails current_page? “fails” when method is POST

别等时光非礼了梦想. 提交于 2020-12-25 03:51:55

问题


I have a really simple problem. I have a page of reports and each report has its own tab. I'm using current_page? to determine which tab should be highlighted. When I submit any report, current_page? doesn't seem to work anymore, apparently because the request method is POST.

Is this the intended behavior of current_page? I have a hard time imagining why that would be the case. If it is, how do people normally get around this problem?

Here's an example of a current_page? call:

<li><%= link_to "Client Retention", reports_client_retention_path, :class => current_page?(reports_client_retention_path) ? "current" : "" %></li>


回答1:


All right, it looks like I figured out the answer to my own question about 5 minutes after putting up a bounty. It looks like current_page? will always return false on POST.

Here's the source code for current_page?:

# File actionpack/lib/action_view/helpers/url_helper.rb, line 588
def current_page?(options)
  unless request
    raise "You cannot use helpers that need to determine the current "                  "page unless your view context provides a Request object "                  "in a #request method"
  end

  return false unless request.get?

  url_string = url_for(options)

  # We ignore any extra parameters in the request_uri if the
  # submitted url doesn't have any either. This lets the function
  # work with things like ?order=asc
  if url_string.index("?")
    request_uri = request.fullpath
  else
    request_uri = request.path
  end

  if url_string =~ %r^\w+:\/\//
    url_string == "#{request.protocol}#{request.host_with_port}#{request_uri}"
  else
    url_string == request_uri
  end
end

I don't really understand why they would have gone out of their way to make current_page? work only for GET requests, but at least now I know that that's the way it is.




回答2:


You could create a new current_path? method in your ApplicationHelper:

def current_path?(*paths)
  return true if paths.include?(request.path)
  false
end

Pass in one or more paths and it returns true if any match the user's current path:

current_path?('/user/new')
current_path?(root_path)
current_path?(new_user_path, users_path '/foo/bar')

Or, you can create a new current_request? helper method to check the Rails controller + action:

def current_request?(*requests)
  return true if requests.include?({
    controller: controller.controller_name,
    action: controller.action_name
  })
  false
end

Pass in one or more controller + action and it returns true if any match the user's current request:

current_request?(controller: 'users', action: 'new')
current_request?({controller: 'users', action: 'new'}, {controller: 'users', action: 'create'})

==UPDATE==

Ok, I decided to make using current_request? a little less verbose by not requiring that you type out the controller when you are trying to match multiple actions:

def current_request?(*requests)
  requests.each do |request|
    if request[:controller] == controller.controller_name
      return true if request[:action].is_a?(Array) && request[:action].include?(controller.action_name)
      return true if request[:action] == controller.action_name
    end
  end
  false
end

Now you can do this:

current_request?(controller: 'users', action: ['new', 'create'])



回答3:


I was having the same problem when using POST. My solution was to do something like this

def menu_item link_text, link_path
  link_class = (request.original_url.end_with? link_path) ? 'active' : ''
  content_tag :li, link_to(link_text, link_path), class: link_class
end

where link_path is just url_for(action: 'action', controller: 'controller')



来源:https://stackoverflow.com/questions/9749807/rails-current-page-fails-when-method-is-post

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!