68

I have a simple search form in my Rails 3 app:

<%= form_tag search_path, :method => "get" do %>
  <%= text_field_tag :q, params[:q] %>
  <%= submit_tag "search", :name => nil %>
<% end %>

When the user hits the submit button, they get taken to the URL: http://myapp.com/search?utf8=%E2%9C%93&q=foobar (where %E2%9C%93 gets displayed as a checkmark: ✓).

I'm not doing anything with the utf8 parameter, so I want to keep the URL clean by removing it entirely. That is, I want users to get taken to the URL: http://myapp.com/search?q=foobar instead.

How do I do this?

Karol Selak
  • 4,248
  • 6
  • 35
  • 65
grautur
  • 29,955
  • 34
  • 93
  • 128
  • 3
    so what did you do eventually? just leave it there? –  Jan 13 '11 at 17:22
  • 3
    shingara's answer on http://stackoverflow.com/questions/4104474/ works: just use `
    ...
    ` rather than `<%= form_tag %>...<% end %>`. Note that you should only do this if the submitted content can never end up in your database, as explained on http://stackoverflow.com/questions/3222013/ .
    – AlexC Feb 11 '11 at 00:47
  • 2
    It is a very relevant question as I do not want to bother my users with workarounds for a single non-standards-complying browser. I only want this "utf8=✓" for the few IE users I have. – Jarl Jul 04 '12 at 08:34
  • 2
    See [my answer](http://stackoverflow.com/a/28201592/430695) re. the `:enforce_utf8` option for `form_tag`. – Paul Annesley Jan 28 '15 at 20:18
  • if you want to ignore the `utf8` param using Javascript/jQuery serialize, you can use the following: `$("form#my_form :input[name!='utf8']").serialize()`. It will ignore the `utf8` key/value pair in the serialized params – MrYoshiji Nov 16 '15 at 21:02

8 Answers8

41

form_tag in Rails 4.2 (and probably earlier) has a :enforce_utf8 option;

If set to false, a hidden input with name utf8 is not output.

(Same as https://stackoverflow.com/a/28201543/430695)

Community
  • 1
  • 1
Paul Annesley
  • 3,387
  • 22
  • 23
39

Once you understand the purpose of the Rails UTF-8 param, and for some reason you still need to remove it, the solution is easier than you think...just don't use the form_tag helper:

<form action="<%= search_path %>" method="get">
  <%= text_field_tag :q, params[:q] %>
  <%= submit_tag "search", :name => nil %>
</form>
Community
  • 1
  • 1
Andrew
  • 227,796
  • 193
  • 515
  • 708
26

Even though you aren't doing anything with the parameter, Rails is. It's to correct some issues in IE's parameter encoding. Yehuda has more info here:

What is the _snowman param in Ruby on Rails 3 forms for?

Community
  • 1
  • 1
cdmwebs
  • 933
  • 7
  • 13
  • 1
    Is there a way to correct those issues in IE's parameter encoding by adding some default in my controller or whatnot instead? – grautur Dec 20 '10 at 17:52
10

There is gem (utf8_enforcer_workaround) for applying the utf8 param only for non standards complying browsers (or any other logic for that sake). This is handy if you don't want to bother your well behaving users with IE workarounds.

Jarl
  • 2,831
  • 4
  • 24
  • 31
3

I made an initializer to remove the param from GET requests. It's obviously a hack.

This goes in config/initializers/overrides.rb:

# Don't let Rails add a utf8=✓ param to GET forms.
# See http://stackoverflow.com/questions/3222013/what-is-the-snowman-param-in-rails-3-forms-for for details.
module ActionView::Helpers::FormTagHelper
private

  def extra_tags_for_form_with_utf8_param_excluded_from_gets(html_options)
    old = extra_tags_for_form_without_utf8_param_excluded_from_gets(html_options)
    non_get = old.include?('"_method"') || old.include?('"'+request_forgery_protection_token.to_s+'"')
    if non_get
      old
    else
      old.sub(/<[^>]+name="utf8"[^>]+"&#x2713;"[^>]*>/, '').html_safe
    end
  end

  alias_method_chain :extra_tags_for_form, :utf8_param_excluded_from_gets

end

Ideally, Rails should probably have a setting for this, or at least rewrite extra_tags_for_form so it's less messy to patch.

Henrik N
  • 15,786
  • 5
  • 82
  • 131
1

Using before_action and redirecting to another action worked for me. For example, if you are searching for posts, set up a route for search on collection.

resources :posts do
  collection do
    get 'search'
  end
end

and make HTTP GET request for posts#index action.

<%= form_tag posts_path, method: :get do %>
  <%= search_field_tag :q, params[:q], placeholder: "Search posts" %>
  <%= submit_tag "Go" %>
<% end %>

and then in PostsController,

before_action :check_for_query, only: :index

    ... 


private 
  def check_for_query
    redirect_to articles_search_url(q: params[:q]) if params[:q].present?
  end

and call Post.search in posts#search action and render index page.

def search
   Post.search(params[:q])
   render :index
end

The URL will look like /posts/search?q=foo

Ken Hibino
  • 31
  • 4
1

Try this in your ApplicationController:

def default_url_options(options={})
  options.delete('utf8')
end
Jan
  • 1,445
  • 1
  • 16
  • 20
  • This doesn't work, as that method must return a hash and may now return e.g. `nil`. But changing it to return something like `{ utf8: nil }` doesn't have the desired effect either. – Henrik N Jun 05 '12 at 08:03
1

I think we should use: enforce_utf8: false in form_tag.

Ex:

= form_tag search_path, method: :get, id: 'searchForm', enforce_utf8: false
Akiko
  • 51
  • 3