<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Karine Vieira</title>
    <description>The latest articles on DEV Community by Karine Vieira (@karinevieira).</description>
    <link>https://dev.to/karinevieira</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F853909%2Fd028aa31-e550-4bf3-abcd-05d4277f088c.jpeg</url>
      <title>DEV Community: Karine Vieira</title>
      <link>https://dev.to/karinevieira</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/karinevieira"/>
    <language>en</language>
    <item>
      <title>Internacionalização com GetText no Rails</title>
      <dc:creator>Karine Vieira</dc:creator>
      <pubDate>Tue, 20 May 2025 12:13:00 +0000</pubDate>
      <link>https://dev.to/videosdeti/internacionalizacao-com-gettext-no-rails-464c</link>
      <guid>https://dev.to/videosdeti/internacionalizacao-com-gettext-no-rails-464c</guid>
      <description>&lt;p&gt;Quando pensamos em internacionalização (i18n) em projetos Rails, a abordagem mais comum é utilizar a API nativa do framework com chaves de tradução. No entanto, recentemente descobri uma alternativa que torna esse processo mais direto e com maior visibilidade do conteúdo traduzido: o uso do GetText.&lt;/p&gt;

&lt;p&gt;GetText é um framework utilizado no ecossistema Linux, que oferece um conjunto de ferramentas para facilitar a tradução de textos em aplicações. Integrado ao Rails, ele permite uma forma mais automática de localizar strings, sem a necessidade de criar e gerenciar nomes de chaves.&lt;/p&gt;

&lt;p&gt;No modelo tradicional com &lt;code&gt;I18n&lt;/code&gt;, criamos chaves de tradução e mapeamos seus conteúdos em arquivos YML. Nas views, essas chaves são utilizadas da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;".empty_state_message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; Nenhum resultado encontrado&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Já com &lt;code&gt;GetText&lt;/code&gt;, podemos escrever diretamente o texto original:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Nenhum resultado encontrado"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; Nenhum resultado encontrado&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa abordagem destaca imediatamente o conteúdo que será traduzido, tornando o código mais legível e intuitivo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Instalação das Gems
&lt;/h3&gt;

&lt;p&gt;Para integrar o GetText ao Rails, instalei as gems &lt;a href="https://github.com/grosser/gettext_i18n_rails" rel="noopener noreferrer"&gt;gettext_i18n_rails&lt;/a&gt; e &lt;a href="https://github.com/ruby-gettext/gettext" rel="noopener noreferrer"&gt;gettext&lt;/a&gt;. Apesar de &lt;code&gt;gettext&lt;/code&gt; ser uma dependência opcional da &lt;code&gt;gettext_i18n_rails&lt;/code&gt;, vale a pena incluí-la no projeto, pois ela oferece rake tasks bastante úteis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Para adicionar suporte a um novo idioma:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;LANGUAGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xx rake gettext:add_language
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Substitua &lt;code&gt;xx&lt;/code&gt; pelo código do idioma desejado, por exemplo, &lt;code&gt;en&lt;/code&gt; para inglês. A lista completa dos idiomas suportados está disponível &lt;a href="https://github.com/ruby-gettext/gettext?tab=readme-ov-file#translators" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Para buscar traduções ausentes e adicioná-las aos arquivos &lt;code&gt;.po&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rake gettext:find
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configurações iniciais
&lt;/h3&gt;

&lt;p&gt;Depois da instalação, é necessário criar um &lt;em&gt;initializer&lt;/em&gt; para definir os domínios de tradução e os idiomas disponíveis. Para isso, usamos classes da gem &lt;a href="https://github.com/grosser/fast_gettext" rel="noopener noreferrer"&gt;fast_gettext&lt;/a&gt;, já que &lt;code&gt;gettext_i18n_rails&lt;/code&gt; atua como um &lt;em&gt;wrapper&lt;/em&gt; para facilitar a integração do GetText com projetos Rails.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/initializers/gettext_i18n_rails.rb&lt;/span&gt;
&lt;span class="no"&gt;FastGettext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_text_domain&lt;/span&gt; &lt;span class="s2"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="s2"&gt;"locale"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :po&lt;/span&gt;
&lt;span class="no"&gt;FastGettext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default_available_locales&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"pt_BR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"es"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="no"&gt;FastGettext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default_text_domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"app"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa configuração permite organizar as traduções por domínio. No exemplo acima, usei apenas o domínio &lt;code&gt;app&lt;/code&gt; para fins de demonstração, mas é possível definir domínios separados por módulos da aplicação, evitando centralizar todas as traduções em um único arquivo.&lt;/p&gt;

&lt;p&gt;Além disso, ajuste o &lt;code&gt;before_action&lt;/code&gt; responsável por definir o idioma da aplicação para também atualizar o locale do GetText:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; def set_locale
   locale = params[:locale] || I18n.default_locale
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+  FastGettext.set_locale(locale)
&lt;/span&gt;   I18n.locale = locale
 end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por fim, como a aplicação já estava usando &lt;code&gt;I18n&lt;/code&gt; para mensagens de erro do ActiveRecord (e alterar isso demandaria mais esforço), desativei esse comportamento do GetText:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/initializers/gettext_i18n_rails.rb&lt;/span&gt;
&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gettext_i18n_rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use_for_active_record_attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Processo de tradução
&lt;/h2&gt;

&lt;p&gt;Para iniciar o processo de tradução, adicionei um texto usando o método do GetText:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= _("Nenhum resultado encontrado") %&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em seguida, executei a rake task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rake gettext:find
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa rake task escaneia o projeto e adiciona as novas strings aos arquivos &lt;code&gt;.po&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Depois, incluí a tradução correspondente no campo &lt;code&gt;msgstr&lt;/code&gt; de cada arquivo &lt;code&gt;.po&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; # locale/en/app.po
&lt;span class="err"&gt;
&lt;/span&gt; msgid "Nenhum resultado encontrado"
&lt;span class="gd"&gt;-msgstr ""
&lt;/span&gt;&lt;span class="gi"&gt;+msgstr "No result found"
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após atualizar as traduções, é importante rodar a rake task novamente. Isso garante que os arquivos &lt;code&gt;edit.po&lt;/code&gt; sejam atualizados corretamente. Caso contrário, as alterações podem se misturar com novas strings adicionadas posteriormente, o que dificulta o controle de versões e a revisão das mudanças.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Fallback automático
&lt;/h3&gt;

&lt;p&gt;Se uma string não tiver tradução, ou se você esquecer de adicionar, o GetText retorna o valor original por padrão:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Nenhuma categoria encontrada"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; Nenhuma categoria encontrada&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Também é possível fornecer um &lt;a href="https://github.com/grosser/fast_gettext?tab=readme-ov-file#block-defaults" rel="noopener noreferrer"&gt;bloco&lt;/a&gt;. Se esse bloco for passado, seu conteúdo será retornado como valor padrão, o que permite definir um fallback mais explícito:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Não foi encontrada uma tradução"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"Texto alternativo"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; Texto alternativo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pluralização
&lt;/h3&gt;

&lt;p&gt;A pluralização no GetText é semelhante à do I18n do Rails. Para que funcione corretamente, é necessário configurar a regra de plural de cada idioma nos arquivos &lt;code&gt;.po&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;No meu caso, os idiomas configurados ficaram assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;# locale/en/app.po
&lt;span class="gd"&gt;- "Plural-Forms: nplurals=; plural=;\n"
&lt;/span&gt;&lt;span class="gi"&gt;+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;# locale/es/app.po
&lt;span class="gd"&gt;- "Plural-Forms: nplurals=; plural=;\n"
&lt;/span&gt;&lt;span class="gi"&gt;+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;# locale/pt_BR/app.po
&lt;span class="gd"&gt;- "Plural-Forms: nplurals=; plural=;\n"
&lt;/span&gt;&lt;span class="gi"&gt;+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depois disso, basta usar o método &lt;code&gt;n_&lt;/code&gt; passando o singular, o plural e o número.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;n_("tarefa pendente", "tarefas pendentes", @total)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após rodar a rake task &lt;code&gt;gettext:find&lt;/code&gt; , serão geradas as entradas necessárias nos arquivos &lt;code&gt;.po&lt;/code&gt; . Com as chaves criadas, é só adicionar as traduções correspondentes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Traduções dinâmicas
&lt;/h3&gt;

&lt;p&gt;É possível interpolar variáveis dentro das strings normalmente. O conteúdo será exibido dinamicamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Publicado por %{username}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;username: &lt;/span&gt;&lt;span class="vi"&gt;@user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;username&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Se você busca uma forma mais simples e direta de gerenciar traduções, vale a pena experimentar o GetText no seu projeto Rails. A integração é tranquila, o ganho em produtividade é real e você ainda pode manter o I18n do Rails para casos onde preferir.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/grosser/gettext_i18n_rails" rel="noopener noreferrer"&gt;gettext_i18n_rails&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/grosser/fast_gettext" rel="noopener noreferrer"&gt;fast_gettext&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ruby-gettext/gettext" rel="noopener noreferrer"&gt;gettext&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rails</category>
      <category>i18n</category>
      <category>gettext</category>
    </item>
    <item>
      <title>Solving URL Length Issues in Rails Filters and Pagination</title>
      <dc:creator>Karine Vieira</dc:creator>
      <pubDate>Sat, 22 Feb 2025 19:42:52 +0000</pubDate>
      <link>https://dev.to/karinevieira/solving-url-length-issues-in-rails-filters-and-pagination-4a5j</link>
      <guid>https://dev.to/karinevieira/solving-url-length-issues-in-rails-filters-and-pagination-4a5j</guid>
      <description>&lt;p&gt;I’m writing this post because every solution I found involved JavaScript— but I refused to go down that path...&lt;/p&gt;

&lt;p&gt;So, in a project I'm working on, we have a listing of contacts that allows filtering and paging. Among the filter options, we include a list of checkboxes for the client’s categories. Until now, we were making a &lt;strong&gt;GET&lt;/strong&gt; request to apply the filters, and everything was working fine—until a client with more than 100 categories started using the page.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem: URL Length Limits
&lt;/h3&gt;

&lt;p&gt;When using &lt;strong&gt;GET&lt;/strong&gt; requests, filter parameters are sent via &lt;strong&gt;Query Params&lt;/strong&gt;, which append data directly to the URL. While this approach works well for a small number of filters, it becomes problematic as the number of selected options grows. Some browsers and web servers impose strict limits on the maximum URL length they can handle, and exceeding these limits can lead to errors.&lt;/p&gt;

&lt;p&gt;For example, &lt;a href="https://chromium.googlesource.com/chromium/src/+/main/docs/security/url_display_guidelines/url_display_guidelines.md#url-length" rel="noopener noreferrer"&gt;Google Chrome&lt;/a&gt; limits URLs to a maximum length of 2MB. On the server side, web servers like &lt;a href="https://nginx.org/en/docs/http/ngx_http_core_module.html#large_client_header_buffers" rel="noopener noreferrer"&gt;NGINX&lt;/a&gt; limits URLs to &lt;strong&gt;8 KB (8,192 characters)&lt;/strong&gt; via the &lt;code&gt;large_client_header_buffers&lt;/code&gt; directive. If a request exceeds this size, NGINX returns a &lt;strong&gt;414 (URI Too Long)&lt;/strong&gt; error.&lt;/p&gt;

&lt;p&gt;In our case, since each selected category was appended to the URL as a separate query parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;?filter[category_ids][]=1&amp;amp;filter[category_ids][]=2&amp;amp;filter[category_ids][]=3... # and so on
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the URL quickly grew beyond acceptable limits, leading to a &lt;strong&gt;414 (URI Too Long)&lt;/strong&gt; error.&lt;/p&gt;

&lt;h3&gt;
  
  
  Changing the Request to POST
&lt;/h3&gt;

&lt;p&gt;To prevent excessively long URLs, the first step was to change the request from &lt;strong&gt;GET&lt;/strong&gt; to &lt;strong&gt;POST&lt;/strong&gt;, since &lt;strong&gt;POST&lt;/strong&gt; allows us to send data in the request body, keeping the URL short.&lt;/p&gt;

&lt;p&gt;In the routes file, we needed to add a &lt;strong&gt;POST&lt;/strong&gt; route pointing to the controller's &lt;code&gt;index&lt;/code&gt; action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:contacts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only: &lt;/span&gt;&lt;span class="sx"&gt;%i[index new create edit update destroy]&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="ss"&gt;:filter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;on: :collection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;action: :index&lt;/span&gt; &lt;span class="c1"&gt;# renamed the route to avoid conflicts&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we updated the form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;form_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;url: &lt;/span&gt;&lt;span class="n"&gt;filter_contacts_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;method: :post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far, so good.&lt;/p&gt;

&lt;h3&gt;
  
  
  New Issue: Pagination
&lt;/h3&gt;

&lt;p&gt;When trying to use filters along with pagination, we encountered the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ActionController::RoutingError (No route matches [GET] "/contacts/filter"):
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pagy&lt;/strong&gt; makes a &lt;strong&gt;GET&lt;/strong&gt; request, but now we needed the request to be &lt;strong&gt;POST&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Additionally, I noticed that when no filters were applied, the generated link pointed to &lt;code&gt;contacts_path&lt;/code&gt; (which needs to be &lt;strong&gt;GET&lt;/strong&gt;). However, when filters were active, the URL was &lt;code&gt;filter_contacts_path&lt;/code&gt; (which needs to be &lt;strong&gt;POST&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;To simplify this, I set &lt;code&gt;filter_contacts_path&lt;/code&gt; as the default, ensuring the request was always &lt;strong&gt;POST&lt;/strong&gt;. In the controller, I added &lt;code&gt;request_path&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
  &lt;span class="n"&gt;pagy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pagy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Contact&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some_scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;limit: &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;request_path: &lt;/span&gt;&lt;span class="n"&gt;filter_contacts_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This fixed the &lt;strong&gt;RoutingError&lt;/strong&gt;, but introduced a new issue:&lt;/p&gt;

&lt;h3&gt;
  
  
  New Issue: Filters Are Lost on Pagination
&lt;/h3&gt;

&lt;p&gt;The filter was only applied to the first page. When navigating to the second page, the filters disappeared because the parameters were not being sent in the request body. This happens because pagination generates &lt;strong&gt;links&lt;/strong&gt;, not forms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution: Using &lt;code&gt;button_to&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The adopted strategy was to use &lt;code&gt;button_to&lt;/code&gt;, as it generates &lt;strong&gt;hidden inputs&lt;/strong&gt; with the received parameters, ensuring the filters are maintained while navigating through pages.&lt;/p&gt;

&lt;p&gt;Now, following the &lt;a href="https://ddnexus.github.io/pagy/docs/how-to/#using-your-pagination-templates" rel="noopener noreferrer"&gt;Pagy example&lt;/a&gt;, the necessary changes would be applied:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&amp;lt;nav class="pagy nav" aria-label="Pages"&amp;gt;
  &amp;lt;%# Previous page link %&amp;gt;
  &amp;lt;% if pagy.prev %&amp;gt;
&lt;span class="gd"&gt;-   &amp;lt;%= link_to(pagy_url_for(pagy, pagy.prev), { aria_label: "Previous" }) do %&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+   &amp;lt;%= button_to(
+     pagy_url_for(pagy, pagy.prev),
+     { params: request.params.except(:page), aria_label: "Previous" }
+   ) do %&amp;gt;
&lt;/span&gt;      &amp;amp;lt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;% end %&amp;gt;
&lt;span class="err"&gt;
&lt;/span&gt;  &amp;lt;%# Page links %&amp;gt;
  &amp;lt;% pagy.series.each do |item| %&amp;gt;
    &amp;lt;% if item.is_a?(Integer) %&amp;gt;
&lt;span class="gd"&gt;-     &amp;lt;%= link_to(pagy_url_for(pagy, item)) do %&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+     &amp;lt;%= button_to(pagy_url_for(pagy, item), params: request.params.except(:page)) do %&amp;gt;
&lt;/span&gt;        &amp;lt;%= item %&amp;gt;
      &amp;lt;% end %&amp;gt;
    &amp;lt;% elsif item.is_a?(String) %&amp;gt;
&lt;span class="gd"&gt;-     &amp;lt;a role="link" aria-disabled="true" aria-current="page" class="current"&amp;gt;&amp;lt;%= item %&amp;gt;&amp;lt;/a&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+     &amp;lt;%= button_to(nil, { params: request.params.except(:page), aria_current: "page", disabled: true, class: "current" }) do %&amp;gt;
&lt;/span&gt;        &amp;lt;%= item %&amp;gt;
      &amp;lt;% end %&amp;gt;
    &amp;lt;% elsif item == :gap %&amp;gt;
&lt;span class="gd"&gt;-     &amp;lt;a role="link" aria-disabled="true" class="gap"&amp;gt;&amp;amp;hellip;&amp;lt;/a&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+     &amp;lt;%= button_to(nil, { params: request.params.except(:page), disabled: true, class: "gap" }) do %&amp;gt;
&lt;/span&gt;        &amp;amp;hellip;
      &amp;lt;% end %&amp;gt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;% end %&amp;gt;
&lt;span class="err"&gt;
&lt;/span&gt;  &amp;lt;%# Next page link %&amp;gt;
  &amp;lt;% if pagy.next %&amp;gt;
&lt;span class="gd"&gt;-   &amp;lt;%= link_to(pagy_url_for(pagy, pagy.next)), { aria_label: 'Next' }) do %&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+   &amp;lt;%= button_to(
+     pagy_url_for(pagy, pagy.next),
+     { params: request.params.except(:page), aria_label: "next" }
+   ) do %&amp;gt;
&lt;/span&gt;      &amp;amp;gt;
    &amp;lt;% end %&amp;gt;
  &amp;lt;% end %&amp;gt;
&amp;lt;/nav&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, it was necessary to remove the &lt;code&gt;page&lt;/code&gt; parameter from the request, as it was being sent in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As a &lt;strong&gt;hidden field&lt;/strong&gt; (indicating the current page)&lt;/li&gt;
&lt;li&gt;In the &lt;strong&gt;URL&lt;/strong&gt; (indicating the next page)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we didn’t remove it, Rails would end up using the current page instead of the next one.&lt;/p&gt;

&lt;p&gt;And that’s it! 🎉 Now the page works normally, without gigantic URLs and without adding JavaScript code.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>filter</category>
      <category>pagination</category>
    </item>
  </channel>
</rss>
