What is the best way in Rails to determine if two

2019-06-18 15:17发布

问题:

I'm wanting a method called same_url? that will return true if the passed in URLs are equal. The passed in URLs might be either params options hash or strings.

same_url?({:controller => :foo, :action => :bar}, "http://www.example.com/foo/bar") # => true

The Rails Framework helper current_page? seems like a good starting point but I'd like to pass in an arbitrary number of URLs.

As an added bonus It would be good if a hash of params to exclude from the comparison could be passed in. So a method call might look like:

same_url?(projects_path(:page => 2), "projects?page=3", :excluding => :page) # => true 

回答1:

Here's the method (bung it in /lib and require it in environment.rb):

def same_page?(a, b, params_to_exclude = {})
  if a.respond_to?(:except) && b.respond_to?(:except)
    url_for(a.except(params_to_exclude)) == url_for(b.except(params_to_exclude))
  else
    url_for(a) == url_for(b)
  end
end

If you are on Rails pre-2.0.1, you also need to add the except helper method to Hash:

class Hash
  # Usage { :a => 1, :b => 2, :c => 3}.except(:a) -> { :b => 2, :c => 3}
  def except(*keys)
    self.reject { |k,v|
      keys.include? k.to_sym
    }
  end
end

Later version of Rails (well, ActiveSupport) include except already (credit: Brian Guthrie)



回答2:

Is this the sort of thing you're after?

def same_url?(one, two)
  url_for(one) == url_for(two)
end


回答3:

def all_urls_same_as_current? *params_for_urls
  params_for_urls.map do |a_url_hash| 
    url_for a_url_hash.except(*exclude_keys)
  end.all? do |a_url_str|
    a_url_str == request.request_uri
  end
end

Wherein:

  • params_for_urls is an array of hashes of url parameters (each array entry are params to build a url)
  • exclude_keys is an array of symbols for keys you want to ignore
  • request.request_uri may not be exactly what you should use, see below.

Then there are all sorts of things you'll want to consider when implementing your version:

  • do you want to compare the full uri with domain, port and all, or just the path?
  • if just the path, do you want to still compare arguments passed after the question mark or just those that compose the actual path path?