Globalize i FormHelper

Od pewnego czasu szukam rozwiązania pozwalającego na wprowadzanie danych w aplikacji wielojęzykowej nie jakoś nie mogę trafić na rozsądną propozycję. Dlatego popełniłem coś takiego:

[code=ruby]<% form_for(@group) do |f| %>

    <% SUPPORTED_LOCALE.each do |l| -%>
  • <%= link_to_function(l,nil,:id=>"tabnav_#{l}") do |page| page <
  • <% end -%>
<% f.fields_for :globalize_translations do |g| %>
<%= g.hidden_field :locale %> <%= g.text_area :name,:size=>'35x5' %>
<% end %> ...[/code] I to działa całkiem przyzwoicie. Tyle tylko, że podobny kod będzie się powtarzał w wielu miejscach aplikacji. Lepiej by było gdybym zamiast tego kodu mógł wpisać np. [code=ruby]<% form_for(@group) do |f| %> ... f.globalize_text_area :name, :size=>'35x5'[/code] Czyli do FormBuildera powinienem dodać metodę ale jak to zrobić? Wiele stron pokazuje jak budować własne wersje FormBuildera ale znalazłem tylko jedną, która pokazuje rozwiązanie zbliżone do tego co potrzebuję http://blog.jepamedia.org/2008/12/20/rails-extend-formhelper-for-custom-form-elements/ . Niestety, chyba czegoś nie rozumiem bo cały czas otrzymuję błąd: "undefined method `globalize_text_area' for #". Czyli metoda FormBuildera wykonuje się ale nie może znaleźć metody w module "MyFormHelper". [code=ruby]module ActionView module Helpers module MyFormHelper def globalize_text_area(object_name, method, options = {}, html_options = {}) s_obj = object_name.to_s content_tag :div, :id=>"#{s_obj}_tabnav" do content_tag :ul do SUPPORTED_LOCALE.each do |l| content_tag :li do capture link_to_function(l,nil,:id=>"tabnav_#{l}") do |page| page <"#{s_obj}_tabnav_content", :id=>"#{g.object.locale}", :style=>"display: none" do capture g.hidden_field(:locale) capture g.text_area(method, options, html_options) end end capture do update_page_tag do |page| page << "$$('div.#{s_obj}_tabnav_content').first().show()" end end end end
class FormBuilder
  def globalize_text_area(method, options = {}, html_options = {})
    @template.globalize_text_area(@object_name, method, objectify_options(options), @default_options.merge(html_options))
  end
end

end
end[/code]
Możliwe, że w tym kodzie są nawet poważne błędy ale puki nie zadziała wywołanie helpera to nie dowiem się gdzie.

Podpowiedzcie gdzie szukać rozwiązania, może jakiś manual, może plugin robiący podobne sztuczki …

Jakoś nikt nie podjął tematu ale … żeby nie zostawić problemu bez rozwiązania …
Udało mi się stworzyć działające rozwiązane w formie pluginu (mój pierwszy :slight_smile: )

# <plugin_dir>/init.rb require 'globalize_fields' ActionView::Base.send :include, GlobalizeFields

[code=ruby]# <plugin_dir>/lib/globalize_fields.rb
module GlobalizeFields
LANGUAGES=[[“bg”,“Български”],[“cz”,“Český”],
[“en”,“English”],[“de”,“Deutsch”],[“fr”,“Français”],
[“hu”,“Magyar”],[“it”,“Italiano”],[“pl”,“Polski”],
[“ro”,“Română”],[“ru”,“Pусский”],
[“sl”,“Slovenský”],[“sp”,“Español”],
[“ua”,“Yкраїнський”]]

def globalize_tabs(object_name)
concat(content_tag(:div, nil, :id=>"#{object_name}tabnav", :class=>“tabnav”) do
concat(content_tag(:ul) do
(I18n.available_locales - [:root]).map do |l|
lang = LANGUAGES.assoc(l.to_s)[1]
content_tag(:li) do
link_to_function(lang,nil,:id=>"tabnav
#{l}") do |page|
page << “$$('div.#{object_name}tab_content’).each(function(item){item.hide()})"
page << “$$(’.tab_active’).each(function(item){item.removeClassName(‘tab_active’)})”
page["#{object_name}tab_content#{l}"].show()
page["tabnav
#{l}”].addClassName(‘tab_active’)
end
end
end
end)
end)
end

def globalize_show_first(object_name)
concat(update_page_tag do |page|
page << “$$(‘div.#{object_name}_tab_content’).first().show()”
page << “$$(‘div.tabnav a’).first().addClassName(‘tab_active’)”
end)
end

end

module ActionView
module Helpers
class FormBuilder
def globalize_fields(*args, &block)
@template.concat(%Q!

!)
@template.globalize_tabs(@object_name)
fields_for(:globalize_translations, *args) do |g|
@template.concat(%Q!
! ) block.call(g) @template.concat("
") end @template.globalize_show_first(@object_name) @template.concat("
") end end end end[/code] I jeszcze przykład zastosowania: [code=ruby]# app/models/group.rb class Group < ActiveRecord::Base translates :name has_many :features
accepts_nested_attributes_for :globalize_translations

end

app/views/groups/new.html.erb

<% form_for(@group) do |f| %>
<%= render :partial => “form”, :locals => { :f => f } %>

<%= f.submit t('common.Create') %>

<% end %>

app/views/groups/_form.html.erb

<%= f.error_messages %>

<%= f.label :index %> <%= f.text_field :index, :maxlength=>3 %>

<% f.globalize_fields do |g| %> <%= g.hidden_field :locale %> <%= f.label :name %> <%= g.text_area :name,:size=>'35x5' %> <% end %>[/code] Kod pluginu nie jest jakiś szczególnie piękny ale działa. Może ktoś bardziej doświadczony zechciałby go skomentować/poprawić i możliwe że komuś się przyda takie rozwiązanie.