Rails N'Ruby1.9

Wiem, że temat przewijał się już parę razy przez forum, ale zawsze jakoś tak mało konkretnie…

Wczoraj spędziłem kilka godzin bawiąc się w usiłowanie zmuszenia do współpracy moich aplikacji railsowych z rubym 1.9.1. Powstawiałem wszystkie # encoding: utf-8, ustawiłem Encoding.default_external na utf-8, żeby dobrze czytał YAMLa, ale nadal nie potrafię obejść

incompatible character encodings: ASCII-8BIT and UTF-8

Sprawdziłem file -i i faktycznie sporo plików jest zakodowana w us-ascii, ale są to raczej pliki “systemowe”, a w każdym razie nie zawierające żadnych stringów z niełacińskimi znakami tak na oko.

Próbowałem też tego hacka, ale nadal bez sukcesu. Baza jest w utf-8, uprzedzając pytania. MySQL 5.1.42.

Ktoś ma jakieś dalsze pomysły (oprócz przekodowywania na siłę wszystkich plików w us-ascii na utf-8, co zapewne i tak nic nie da)?

Baza może i jest w UTF, a w jakim kodowaniu driver zwraca ciągi wyciągnięte z tej bazy? Nie sugeruj się encoding: utf8 w database.yml bo żaden driver nie zwraca na to uwagi.

Jakie kodowanie mają ciągi zapisane w haszu params?

Nie wiem w jakim zwraca driver (tzn. nie wiem, czy w innym), ale >> n.last.title.encoding => #<Encoding:UTF-8>
Natomiast params faktycznie jest w US-ASCII.

Spoko - widocznie trochę się w tej kwestii już pozmieniało ;-). Zwykle używałem sqlite3-ruby i pg, tam chyba dalej jest ASCII-8BIT.

No to chyba masz odpowiedź - powinieneś zrobić before_filter w application, który zamienia wszystkie parametry na kodowanie utf.

Co do samego tematu, to sporo zebrałem w tym wątku. Jak znajdziesz coś nowego, to dodaj właśnie tam rozwiązanie.

Swoją drogą udało już się komuś szczęśliwie napisać/przeportować i postawić aplikację na kombosie ruby 1.9.1 + rails 3? :slight_smile:

Ja próbowałem w ten weekend i się poddałem. Rails 3 będzie fajne, ale jest jeszcze sporo problemów i – przede wszystkim – niekompatybilnych bibliotek.

Ja postawiłem rails 3 + mongomappera + cucumber + rspec + factory girl :slight_smile:

Część z moich poprawek już jest wciągnięta do cucumbera i chyba factory girl, dużo z tym problemów nie było.

Mi się udało wczoraj wieczorem. :smiley:
Zarówno z mysql, jak i pg – czyli można pisać prawdziwe aplikacje :slight_smile:

Szybkość kombosa ruby 1.9 + rails3 powala (wygenerowanie aplikacji to ułamek sekundy).

RVM jest absolutną rewelacją.

Niestety jest jakiś babol związany z bundlerem/gemami i na ruby 1.9.1 pluje mi całymi stronami warningów przy starcie aplikacji.
Na ruby 1.9.2 (poza powyższym babolem z bundlerem) mam jakiegoś brutalnego segfaulta, na szczęście z dość bogatym wyjściem, więc pewnie jeszcze dziś zrobię ticket.

Myślę że na wiosnę zacznie się wielkie dostosowywanie pluginów, bo reszta stosu będzie śmigać.

Zgadzam się.

Aha, czyli to wystąpiło nie tylko u mnie – na 1.8.7 nie sprawdzałem. Ponadto Netbeans się wykrzacza na otwieraniu projektu Rails 3, a praca w czymkolwiek innym (poza może RubyMine) mnie odstrasza (tak wiem, lamię).

Co do szybkości generowania aplikacji to chyba jest mi to obojętne. Najważniejsza jest szybkość serwowania requestów, a tu widać znaaaczna poprawę. Nowe helpery javascriptowe - bombastic. Będzie dobry rok :smiley:

Projekt na uczelnie robie na Rails 3 + Ruby 1.9.1 i wszystko smiga. Bundler head poprawil troche warningow, ale dalej troche wywala.

Troche sie dziwie ze nie dodali do AR bulk import, musialem sobie ukrasc z ar-extensions.

Widzieliscie gdzies w necie rdoca aktualnego?

RVM :slight_smile: na gentoo są sloty od zawsze i można każdej aplikacji mieć dowolne wersje i rodzaje.

[code]laptop ~ # eselect ruby list
Available Ruby profiles:
[1] ruby18 (with Rubygems)
[2] ruby19 (with Rubygems) *

laptop ~ # ruby -v
ruby 1.9.1p243 (2009-07-16 revision 24175) [x86_64-linux]
laptop ~ # eselect ruby set 1
Successfully switched to profile:
ruby18
laptop ~ # ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux]
laptop ~ #[/code]
No ale nie będę tutaj zaczynał wojny i zachęcał programistów do zainteresowania się innymi dystrybucjami Linux niż Ubuntu.

Jest bliżej niż myślisz :wink:

gem server

A póżniej
http://localhost:8808/
lub odrazu
http://localhost:8808/doc_root/actionpack-3.0.0.beta/rdoc/index.html
http://localhost:8808/doc_root/actionmailer-3.0.0.beta/rdoc/index.html
http://localhost:8808/doc_root/activemodel-3.0.0.beta/rdoc/index.html
http://localhost:8808/doc_root/activerecord-3.0.0.beta/rdoc/index.html
http://localhost:8808/doc_root/activeresource-3.0.0.beta/rdoc/index.html
http://localhost:8808/doc_root/activesupport-3.0.0.beta/rdoc/index.html

Tak więc. Nawijki ciąg dalszy. Przyznam szczerze, że sprawę Railsów i Ruby 1.9 prześledziłem na tyle dokładnie na ile pozwalały mi aktualne umiejętności. Dalej jednak nie potrafię się uporać z błędem “incompatible character encodings: UTF-8 and ASCII-8BIT”. Dodam jeszcze, że nie mam zielonego pojęcia co dokładnie szwankuje. Odpowiedzi na temat tego problemu w większości sprowadzały się do: "Ruby 1.9 jeszcze nie … używać ruby 1.8.7 " no właśnie. Takie odpowiedzi miały miejsce dobre pół roku temu. Jak więc jest teraz?

Jeżeli chodzi o mój problem, postaram się go jak najlepiej określić.

  • ów komunikat pojawia się nie wtedy, kiedy chcę w widoku przedstawić elementy z bazy danych, ale … kiedy przedstawiam elementy za pomocą partiala.
  • komunikat występuje tylko wtedy, kiedy elementy bazy danych ukazywane za pomocą partiala mają w sobie polskie znaki (czy tam inne utfowe). Elementy ukazywane bezpośrednio działają bez problemu.
  • w przypadku, gdy próbuje ustawić kodowanie właśnie na ASCII-8BIT, pojawia się ten sam komunikat, ale kolejność wymienionych kodowań jest odwrotna

Jeżeli chodzi o fizyczny wygląd:

<% @posts.each do |p| %>
<%= p.title %>
<%= p.content %>
<% end %>

Uruchamia się ładnie nawet z polskimi znakami.

<%= render :partial => ‘posts’ %> gdzie w partialu znajduje się ten sam kod co powyżej

Wali błędami.

Jeżeli chodzi o kodowanie elementów bazy danych.
p.title.encoding (jeżeli nie ma polskich znaków) —> utf-8
p.title.encoding (jeżeli są polskie znaki) —> ascii-8bit

Tak więc… byłbym wdzięczny za uświadomienie.

Sprawa jest jeszcze ciężka w Rails 3.

W konsoli Encoding.default_internal i Encoding.default_external ustawione na UTF-8, czyli otrzymasz #Encoding:UTF-8, czy też sprawdając poprzez ENCODING. Tylko w konsoli wszystko gra. (EDIT)

Z requestami wychodzi na to, że sprawa gdzieś leży po stronie Rack.a, mimo, że przeglądarka wyśle w UTF-8, oczywiście przyjmując, że tak ‘standardowo’ się zachowa a nie musi, to i tak Rack dla bezpieczeństwa potraktuje jako binary string czyli ASCII-8BIT i postara się przekodować. No i się zaczyna, gdzie jest problem. Jest łatwe załatanie problemu w Rails 2.3.* aby na siłę przekodować na UTF-8. Znajdziesz patch.e dla mysql, request.ów i render.owania. W sumie to w większości przypadków to właśnie drivery baz i enginy templat.ów powinny to za Ciebie robić. Zawsze możesz w innych przypadkach posiłkować się force_encoding(‘utf-8’) na string.ach.

A może ktoś już znalazł wygodne rozwiązanie dla Rails 3. W necie tak sobie z rozwiązaniami, mam zbyt dużo na głowie, ale koniec końców chyba będę zmuszony napisać patcha.

Nie mam pod ręką, ale znalazłem na sieci patch (nie pamiętam, czy na MySQL, czy na ActiveRecord), który na wszystkie stringi nakładał force_encoding. Testowałem to na jednej aplikacji i z tekstami ciągniętymi z bazy nie było żadnych problemów.

Nie mam natomiast pojęcia jak to się odbija na wydajności aplikacji.

Tak też znalazłem patch.e rozwiązujące problem dla Rails 2.3.* np. http://snaprails.tumblr.com/post/556378216/porting-an-application-to-ruby-1-9

Korzystam wyłącznie z MongoDB z racji architektury aplikacji, oczywiście w Mongo kodowanie jest tylko utf-8, więc krótko, nie ma problemu.
Jednakże to co z Rack.a (1.1.0, 1.0.1) do Rails przekazywane jest jako ASCII-8BIT. I tu trzeba pobawić się na przekodowanie. Czytałem, że z Rack.iem i kodowaniem miał problem gościu z umlautami, nie dziwię się, że musiał go patch’ować. Cóż, myślę, że na Rack.u się skupię.

Tematyka, problematyka, rozwiązania dla Rails 2.3.* i Ruby 1.9: https://rails.lighthouseapp.com/projects/8994/tickets/2188-i18n-fails-with-multibyte-strings-in-ruby-19-similar-to-2038 http://rack.lighthouseapp.com/projects/22435/tickets/48-rackutilsunescape-problems-in-ruby-191#ticket-48-1

Dla dążących do celu tekst http://yehudakatz.com/2010/05/17/encodings-unabridged

W Ruby 1.9.1 o kodowaniu pliku źródłowego decyduje komentarz w pierwszej (lub drugiej) linii tego pliku, np:

# encoding: UTF-8

Jeśli tego nie ma to plik uznawany jest za ASCII-8BIT. Tak naprawdę oznacza to brak jakiegokolwiek konkretnego kodowania. W związku z tym string zwrócony przez render (np zawierający wyrenderowany partial) ma kodowanie ASCII-8BIT.

Sytuacja wygląda mniej więcej tak:

[code=Ruby]template = “ą”
template.force_encoding ‘ASCII-8BIT’ # w ERB będzie on miał takie kodowanie

c = “ć”
c.force_encoding ‘UTF-8’ # jakiś string zwrócony z np bazy danych

template << c # wyjątek: Encoding::CompatibilityError: incompatible character encodings: ASCII-8BIT and UTF-8[/code]
Ostatnia operacja powinna być dozwolona - w końcu dodajemy string UTF-8 do stringa binarnego. Podobno w 1.9.2 ma to być zmienione.

Nie wiem czy da się powiedzieć Ruby, że szablon ERB jest UTF-8. Obecnie pozostaje robić force_encoding(‘ASCII-8BIT’) na poziomie sterownika bazy danych lub zmusić ERB w jakiś sposób do traktowania szablonów jako UTF-8.

Yehuda Katz ma serię szczegółowych postów na temat kodowania znaków w 1.9.1. Polecam. :slight_smile:

@filiptepper String#force_encoding tylko ustawia zmienną instancyjną na podane kodowanie. Jest to szybka operacja, ponieważ nie ma żadnego sprawdzenia czy String jest kompatybilny z nowym kodowaniem.

W przypadku MongoDB to nie ma problemu w jakim kodowaniu trafiają dane do Rails.ów, w sensie z ‘zewnątrz’, ponieważ baza sama przekoduje na UTF-8.

Problem zaczyna się w samych Rails.ach 3 beta, w sumie to już z Rack’a wychodzi ASCII-8BIT w przypadku użycia np. polskich znaków. Obojętnie co i jak poustawia się z dostępnych opcji i możliwości to nic to nie zmieni. Efektem będą błędy tak jak już wyżej zostało wymienione. Pozostaje na siłę ustawiać UTF-8 za pomocą String#force_encoding. Lub jeśli ktoś woli, jeśli używa tylko utf-8 to spatchować Rack.a.
Na blogu Yehuda Katz zaznaczył iż są świadomi tego błędu też i w Rack będzie poprawiany.

Dla mnie dziś też problemy z kodowaniem były powodem sporej frustracji. Umieszczone w templacie polskie znaki działały normalnie… dopóki nie były opakowane w form_for. Gdy były - nie było na to mocnych. Pluł się coś o funkcję concatenate, więc zapewne jest to głębiej w samych railsach umieszczone, niż mogłoby się wydawać. Rozwiązania nie znalazłem, próbuję dalej.