Friday, March 28, 2008

Rails a upload plików z klasą polimorficzną (Attachment_fu)

Polecam zainstalowanie plug-inu Attachment_fu


script/plugin install http://svn.techno-weenie.net/projects/plugins/attachment_fu


Następnie tworzymy model np. File /lub plik - tworząc odpowiednie inflections/, czyli


scrip/generate model Plik


w stworzona migracja powinna wyglądać następująco:


class CreatePliki < ActiveRecord::Migration
def self.up
create_table :pliki do |t|
t.column :filename, :string
t.column :size, :integer
t.column :content_type, :string
t.column :thumbnail, :string
t.column :parent_id, :integer
t.column :height, :integer
t.column :width, :integer

# Obsługa polimorfizmu
t.column :zasob_id, :integer
t.column :zasob_type, :string

t.timestamps
end
end

def self.down
drop_table :pliki
end
end


A nasz plik modelu powinien zawierać następujący wpis:


class Plik < ActiveRecord::Base
belongs_to :zasob, :polymorphic => true # Polimorfizm

has_attachment :content_type => :image,
:storage => :file_system,
:max_size => 2.megabytes,
:resize_to => '300x300>',
:size => 0..2.megabyte,
:thumbnails => {
:small => '50x50>',
:medium => '100x100>',
:big => '200x200>'
},
:processor => :MiniMagick;

validates_as_attachment
end


Zdefiniowane zostały tutaj opcje zapisu zdjęcia uwzględniające tworzenie miniaturek za pomocą biblioteki MiniMagic. Aby ją zainstalować powinniśmy wpisać w konsoli:

sudo gem install mini_magick

Teraz wiążemy nasze zdjęcie z jakąś istniejącą klasą modelu. W naszym przypadku niech będzie nią klasa produkt:


class Produkt < ActiveRecord::Base

has_and_belongs_to_many :kategorie
belongs_to :producent

has_one :plik, :as => :zasob #,:class_name => 'Plik'

validates_presence_of :nazwa, :message => "nie może być pusta"
validates_presence_of :cena, :message => "nie może być pusta"

validates_length_of :nazwa, :minimum=>2, :message=> "musi składać się przynajmniej z dwóch znaków"
validates_numericality_of :cena, :greater_than_or_equal_to => 0, :message => "nie może być ujemna"

end


W następnej kolejności musimy uzupełnić widoki o możliwość dodawania oraz wyświetlania naszego obrazka. W formularzu dla akcji new oraz edit powinniśmy mieć następujący wpis


<% form_for(@produkt, :html => { :multipart => true }) do |f| %>
....
<%= file_field :plik, :uploaded_data %>
....
<% end %>


Musimy również uzupełnić nasz kotroler o zapis załączonego pliku. W akcji update oraz create należy dodać następujący kod:


unless params[:plik].blank?
@produkt.plik = Plik.new(params[:plik])
p.save
end


Wyświetlić nasz załączony plik możemy w następujący sposób:


<%= image_tag(@produkt.plik.public_filename(:big)) if @produkt.plik%>


gdzie :big to nazwa thumbnailsa podana w modelu. Jeżeli nie podamy tego parametru wyświetlony będzie oryginalny obrazek.

Przedstawiłem podstawowe kroki niezbędne do dodania możliwości przechowywania plików związanych z naszymi klasami modelu. Po więcej informacji odsyłam do:

http://www.railslodge.com/plugins/108-attachment-fu
http://clarkware.com/cgi/blosxom/2007/02/24
http://blog.defv.be/2007/12/19/attachment_fu-with-polymorphic-association
http://khamsouk.souvanlasy.com/2007/5/1/ajax-file-uploads-in-rails-using-attachment_fu-and-responds_to_parent

Ruby MySQL i UTF8

Najprostszy sposób na ustawienie MySQL do pracy w UTF-8, to modyfikacja pliku my.cnf. Plik ten znajduje się w katalogu /etc/mysql/my.cnf. W pliku tym w sekcji zmodyfikować 2 sekcje [mysqld] oraz [client]:

[mysqld]
character-set-server = UTF8
default-character-set = UTF8
collation_server = utf8_polish_ci

[client]
default-character-set=utf8

Następnie aby ruby poprawnie radził sobie z zapisem do tak stworzonej bazy należy zmodyfikować plik environment.rb znajdujący się w podkatalogu /config/. Do pliku tego dodajemy następujący wpis:

config.action_controller.default_charset = "utf-8"

Jeżeli tworzyliśmy projekt za pomocą rails -d mysql nazwa_projektu automatycznie w pliku konfigurującym połączenie z baza danych powinniśmy otrzymać podobny zestaw wpisów:

development:
adapter: mysql
encoding: utf8
database: projekt_development
username: root
password:
socket: /var/run/mysqld/mysqld.sock

/Podobmne wpisy będą wygenerowane również dla środowiska test oraz production/


Uwaga: jeżeli pomimo wprowadzenia zmian opisanych powyżej nasza baza danych dalej błędnie obsługuje polskie znaki dialektyczne, najprostszym sposobem aby sobie z tym poradzić jest usunąć wszystkie tabele i stworzyć je na nowo /rake db:create:all oraz rake migrate/.

Thursday, March 20, 2008

Ruby on Rails - polskie komunikaty błędów przy walidacji

W przypadku używania walidatorów dla stron polskojęzycznych pojawia się problem z niezręcznymi angielskimi komunikatami błędów. Aby spolonizować w prosty sposób nasze komunikaty wystarczy dokonać tylko kilku modyfikacji.

Załóżmy, że w naszym modelu mamy następującą klasę:

class Produkt < ActiveRecord::Base
#pola => Nazwa, Cena,
end

Spolonizowana walidacja mogłaby wyglądać w takim przypadku następująco:

class Produkt validates_presence_of :nazwa, :message => "nie może być pusta"
validates_presence_of :cena, :message => "nie może być pusta"

validates_length_of :nazwa, :minimum=>2, :message=> "musi składać się przynajmniej z dwóch znaków"
validates_numericality_of :cena, :greater_than_or_equal_to => 0, :message => "nie może być ujemna"

end

W tym momencie część pracy już za nami. Metoda

<%= error_message_for :produkt -%>

działa już prawie tak jak byśmy chcieli. Pozostaje usunięcie nagłówka i wstępnego komunikatu, który w dalszym ciągu pojawia się w języku angielskim. Rozwiązanie jest dość trywialne (oczywiście jeżeli wiadomo gdzie szukać). Poprawiona wersja metody wygląda więc tak:

<%= error_messages_for :produkt, :header_message => "Błąd !", :message => "Lista błędów:"%>

Polecam również lekturę:
http://www.rubyonrails.pl/forum/p3572-2007-10-22-00:50:44

Wednesday, March 19, 2008

Rails paginacja z polskimi nazwami w osobnej metodzie helpera

Aby nie powielać wpisywanego kodu paginatora (will_paginate) parametryzując go o polskie napisy dla przycisków 'next' i 'previous' możemy stworzyć oddzielną metodę w module ApplicationHelper.


def paginacja(kolekcja)
will_paginate kolekcja,
:inner_window => 10,
:outer_window => 10,
:prev_label => "« Poprzednie",
:next_label => "Następne »"
end


Następnie w widoku możemy wywołać tą metodę w następujący sposób.

<%= paginacja @produkty %>


Oczywiście aby działała cała paginacja należy zainstalować plugin will_paginate oraz przygotować odpowiednio kolekcję w kontrolerze:


@produkty = Produkt.paginate(:order => 'nazwa DESC',
#:conditions => ["active = ?", 1]
:per_page => 10,
:page => params[:page])


Jeżeli przeczytałeś ten artykuł do końca to prawdopodobnie zainteresuje Ciebie również paginacja w Rails 2.1

Umieszczenie grafiki w link_to

Aby umieścieć obrazek w hiperłączu wystarczy w widoku *.html.erb dodać następującą linijkę:

<%= link_to image_tag("obrazek.gif", :border=>0), :action => 'akcja', :id => obiekt %>

Tuesday, March 18, 2008

Ruby on Rails 2.0.2 i inflections (polski pluralize)

Ruby posiada fantastyczną cechę jaką jest możliwość odmiany rzeczowników i na ich podstawie automatycznego tworzenia nazw tabel oraz kontrolerów. Niestety własność ta działa standardowo tylko dla języka angielskiego. Jeżeli chcemy jednak aby w naszym projekcie była możliwość posługiwania się nazwami polskimi możemy dodać nowe reguły do railsa, które umożliwią mu odmianę polskich wyrazów.

Sprawa odmiany wydaje się w railsie 2.0.2 dość trywialna. Wystarczy dodać do pliku config/initializers/inflections.rb kilka linijek. Pamiętajmy jednak, że rails do prawidłowego działania potrzebuje poprawnie zdefiniowane reguły dla języka angielskiego dlatego nie usuwajmy tych reguł metodą clear :all.

Nowe polskie rzeczowniki możemy dodawać jako rzeczowniki nieregularne i w takim przypadku rails nie protestuje i wszystkie inne funkcjonalności powinny działać poprawnie wpisujemy więc:

Inflector.inflections do |inflect|
inflect.irregular 'konto', 'konta'
end

I wywolujac "script/generate model Konto uzytkownik:string haslo:string", a następnie "rake db:migrate" w naszej bazie danych powstanie tabela konta.

Problem pojawi się jeżeli będziemy chcieli użyć naszych rzeczowników w metodzie scaffold. Domyślnie nie są generowane odpowiednie ścieżki routingu dlatego musimy to naprawić wpisując:

rake routes

Od teraz możemy cieszyć się polskimi nazwami w railsie.