Tłumaczenia i globalize2

Witam,

W ramach rozpoczęcia swojej przygody z rubym i railsami próbuje napisać aplikację obsługującą kila wersji językowych używam do tego celu globalize. Problem dodawania tłumaczeń do strony w panelu administracyjnym rozwiązałem następująco -> w momencie dodawania nowego rekordu do bazy element zapisywany jest w domyślnym języku aplikacji i po pozytywnym zapisie użytkownik jest przekierowywany do edycji tam do podstawowego formularza doklejane są dwa pola: język wpisu 1) wybierz z listy (select z oznaczeniami języka (z pola locale w tabeli tworzonej przez globalize modelu) i 2) zdefiniuj nowy - zwykły input do wpisania języka dla którego nie ma jeszcze żadnych tłumaczeń.
W momencie wybrania jednego z języków z listy wysyłane jest ajaxowy request i pobierane są wybrane elementy rekordu dla którego dostępne są tlumaczenia dla wybranego języka.

Wygląda to mniej więcej tak, w modelu którego elementy chce tłumaczyć na kilka języków defniuje:

listę pól do tłumaczenia

TRANSLATES = [:title, :name, :description] translates *TRANSLATES
metodę potrzebną mi do uzupełnienia selecta z dostępnymi tłumaczeniami

[code]def self.locales
find_by_sql(“SELECT DISTINCT locale FROM project_translations”)
end

def locales
Project.locales
end

def class_name
self.class.name
end[/code]
Kod który generuje tabelkę z zapisanymi tłumaczeniami dla wybranego modelu
(<%= render :partial => 'share/translations_table', :locals => { :obj => @project } %>
)

share/translations_table:

[code]

Dostępne tłumaczenia


<% eval(‘l =’ + obj.class_name.capitalize) %>
<% obj.locales.each do |record| %>
<% I18n.locale = record[:locale] %>

język: <%=record[:locale] %>

<% l::TRANSLATES.each do |field| %> <% end %>
<%=eval(obj.class_name.capitalize + '::HUMANIZED_ATTRIBUTES[field]')%> <%=eval('obj.' + field.to_s) %>
<% end %>[/code] Podany przeze mnie kod działa, z tym, że mam kilka modeli dla których chciałbym móc przygotowywać tłumaczenia co wiąże się z tym, że w każdym z tych modeli muszę zdefiniować self.locales, locales i class_name - chciałbym te metody zapisać osobno w module i wmiksować do wybranych modeli, tylko niestety nie bardzo wiem jak. Będę również bardzo wdzięczny za podpowiedzi jak pozbyć się eval z przedstawionego kodu.

EDIT
Jeśli komuś, nie chce się tego wszystkiego czytać to zwężę całość do pytania -> Jak z poziomu metody w module wmiksowanym do klasy uzyskać dostęp do metod z tej klasy?

Mi się nie chciało czytać… mam nadzieję że nie kulą w płot:

[code=ruby]module Mod
def foo
self.bar
self.class.bar
end
end

class Cla
include Mod

def bar
 puts "Jestem metoda obiektu"
end
def self.bar
    puts "Jestem metoda klasy"
end

end

Cla.new.foo

Jestem metoda obiektu
Jestem metoda klasy[/code]

dzięki za odpowiedź

doprecyzuję:
mam model Project który dziedziczy po ActiveRecord::Base więc mogę sobie w tej klasie zadeklarować metodę locales i użyć w niej find_by_sql

def locales find_by_sql("SELECT DISTINCT locale FROM project_translations") end
i teraz ponieważ dokładnie taką samą metodę potrzebuje w kilku modelach chciałbym ją przenieść do modułu i tylko wmiksowywać go sobie do wybranych modeli, ale wywołanie metody find_by_sql w module wmiksowanym w model powoduje zgłoszenie wyjątku

undefined method `find_by_sql'

Ok, chyba wiem w czym tkwi problem. Chcesz dołączyć metody do klasy a nie do instancji klasy. Zastąp “include” poprzez “extend” i powinno działać.

Dzięki - faktycznie z extend działa. W związku z tym mam kilka pytań:

  1. Czy nie ma takiej możliwości aby przedstawiony przeze mnie wyżej kod działał z instancją klasy ? Bo faktycznie w moim pierwotnym założeniu chciałem wywoływać metodę locales na obiekcie klasy a nie na niej samej. Dla pewności chciałem robić tak:

@project = Project.find(params[:id]) @project.locales
a nie

Project.locales

Zasadniczo dla mojego kodu nie ma to znaczenia, ale chciałbym wiedzieć na przyszłość - czy tak się da i jak :slight_smile:

  1. Czy może jest sposób aby z instancji klasy przejść do klasy, chodzi o takie kod:

[code=ruby]class Project < ActiveRecord::Base

def self.locales
find_by_sql(“SELECT DISTINCT locale FROM project_translations”)
end
end

@project = Project.find(params[:id])
klasa =@project.zwroc_klase
klasa.locales[/code]

sam sobie odpowiem na pytanie numer dwa

@project.class.locales

sorry najpierw napisałem potem sprawdziłem - więcej tak nie zrobię :slight_smile:

EDIT jeszcze sam siebie poprawię , może się komuś do czegoś przyda
w pierwszym poście podałem kod:

<%= render :partial => 'share/translations_table', :locals => { :obj => @project } %>

share/translations_table:

[code=ruby]

Dostępne tłumaczenia


<% eval(‘l =’ + obj.class_name.capitalize) %>
<% obj.locales.each do |record| %>
<% I18n.locale = record[:locale] %>

język: <%=record[:locale] %>

<% l::TRANSLATES.each do |field| %> <% end %>
<%=eval(obj.class_name.capitalize + '::HUMANIZED_ATTRIBUTES[field]')%> <%=eval('obj.' + field.to_s) %>
<% end %>[/code] z pytaniem jak pozbyć się z niego eval. Otóż w ten sposób:

[code=ruby]

Dostępne tłumaczenia


<% obj.class.locales.each do |record| %>
<% I18n.locale = record[:locale] %>

język: <%=record[:locale] %>

<% obj.class::TRANSLATES.each do |field| %> <% end %>
<%=obj.class::HUMANIZED_ATTRIBUTES[field]%> <%=obj.send(field) %>
<% end %>[/code]