Pokazywanie postów oznaczonych etykietą Ruby on Rails. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą Ruby on Rails. Pokaż wszystkie posty

środa, 15 stycznia 2020

Utworzenie z konsoli nowego użytkownika Devise w Rails

Niezmiennie zapominam :-)
# Devise
user = User.new(email: 'test@example.com', 
                password: 'password', 
                password_confirmation: 'password')
user.save

wtorek, 7 stycznia 2020

* - (gwiazdka, asterix) czyli operator splat w Ruby

Zasadniczo służy do przyjęcia wielu argumentów do metody. Na przykład tak:
def my_method(*args)
  args.each {|arg| puts arg}
end

a wywołanie:
my_method(:a, "ala ma kota", 1, 2, 3.14)

A tak przy okazji... splat ma sporo więcej możliwości.

Opisane fajnie tutaj: https://www.honeybadger.io/blog/ruby-splat-array-manipulation-destructuring/

środa, 1 lipca 2015

OR zamiast AND w zapytaniach Rails

Przy zapytaniu where - wynikowy SQL jest generowany zazwyczaj z AND. Na przykład w tym zapytaniu wszędzie w SQL'u jest AND:
VariantDetail.joins(product_detail: {product: [:channel, :type]},
                    variant: {starpacks: :version})
             .all_active
             .where(code: cover[:id], value: value,
                    pkb_cats_discr: {percent: percent.to_i},
                    pkb: {channel_id: channel.id, type_id: @type.id},
                    version: {code: ver.code})

Mi zaś, chodziło o to, aby kolumna percent była rozważana dla dwóch wartości: jako 0 (zero) albo NULL.
Okazało się, że można to zrobić w dość prosty sposób. Wystarczy użyć w klauzuli where, tablicy.
Na przykład tak:
{percent: [0, nil]}
co skutkuje takim kompletnym zapisem:
VariantDetail.joins(product_detail: {product: [:channel, :type]},
                    variant: {starpacks: :version})
             .all_active
             .where(code: cover[:id], value: value,
                    pkb_cats_discr: {percent: [0, nil]},
                    pkb: {channel_id: channel.id, type_id: @type.id},
                    version: {code: ver.code})

czwartek, 25 września 2014

Sumowanie wartości w rekordach wybranego już zestawu z bazy danych

Rozważmy taki scenariusz: wybraliśmy wszystkich klientów, którzy w zadanym okresie kupili więcej niż jeden towar z naszego sklepu internetowego. Otrzymaliśmy zestaw klientów wraz z ilością zakupionych towarów i sumą cen tych towarów per klient.
A co jeśli chcemy zsumować ilość wszystkich towarów zakupionych przez klientów w tym zestawie?
Zawsze robiłem to tak:
  @customers.sum(&:amount)
No i fajnie. Działało. Działało do momentu, dopóki nie sumowałem ilości przepracowanych godzin, które to godziny było obliczane z dat. Z niewiadomych przyczyn generowana kolumna była w formacie string i sumowanie tworzyło wielki string.

Można to zrobić tak:
  @customers.sum{|customer| customer.amount.to_i}
Problem znika.

piątek, 19 września 2014

Wstawienie własnego parametru do ścieżki Paperclip'a

W którymś ze swoich projektów potrzebowałem aby obrazki gromadzone przez użytkowników aplikacji gromadzone były w katalogach firm, do których należą owi użytkownicy. Oczywiście w parametrze "path" Paperclip'a nie występuje nic podobnego do "firm_id".

Innymi słowy chciałem zapisać coś takiego:
has_attached_file :scan_picture, :styles => {:thumb => '50x50>'},
                  :default_url => '/images/:style/missing.png',
                  :url => "/system/scan_pictures/:firm_id/:id/:style/:basename.:extension",
                  :path => ":rails_root/public/system/scan_pictures/:firm_id/:id/:style/:basename.:extension"


Jest to jednak możliwe :-)
Zrobiłem tak:
w katalogu /config/initializers stworzyłem plik paperclip_interpolations.rb
w tym pliku umieściłem zapis:
Paperclip.interpolates('firm_id') do |attachment, style|
  attachment.instance.move_out.customer.firm_id.to_s.parameterize
end
Tłumaczyć to można tak:
Weź egzemplarz klasy, która wywołuje dołączanie pliku (attachment.instance), pobierz z niego obiekt wyjazd (move_out), a z niego klienta i firmę, do której klient należy. Przekształć firm_id na string i użyj metody prametrize.
No i aby powyższe lepiej zrozumieć można przytoczyć jeszcze specyfikację MoveOut (wyjazd):
class MoveOut < ActiveRecord::Base
  belongs_to :customer
end

czwartek, 30 stycznia 2014

Dynamiczne dodanie pola do obiektu w Ruby

Czasami takie pole na jakiś czas okazuje się potrzebne.
Więc robię to tak:
@customer = Customer.find(1)
@customer.class.module_eval { attr_accessor :age}
@customer.age = 69 #już niemłody

sobota, 23 lutego 2013

Króciutko o wysyłaniu emaili w Rails

Tworzę sobie model. Roboczo nazwijmy go UserMailer. Dziedziczy on po ActionMailer::Base. W modelu tym ustawiam metody, z których każda jest wzorem wysyłanego emaila.

Na przykład dla newslettera tworzę:
def newsletter(newsletter, email)
  recipients email
  from "#{Options::Program_name} - newsletter :: <#{Options::Email}>"
  subject newsletter.subject
  sent_on Time.now
  body({
               :body => newsletter.body
       })
end
Przekazane parametry to:
  • newsletter - obiekt zawierający dane dla newslettera takie jak choćby temat;
  • email emaile (emaile) do wysyłki
Zmienna generowana przez metodę newsletter, a nazywająca się :body wystąpi w widoku.
Więcej na temat konstrukcji metod dla ActionMailer można znaleźć na stronie rails http://apohllo.pl/guides/action_mailer_basics.html

Jeśli już mam metodę, to przygotowuję dla niej widok. Dla takiej konfiguracji, jaką opisuję widoki winny być umieszczone w folderze /views/user_mailer czyli w nazwie zgodnej z nazwą modelu.

Widok powinien być standardowym plikiem html.erb z dopiskiem .text. W naszym przypadku dla metody newsletter widok powinien się zwać nomen omen newsletter.text.html.erb albo newsletter.text.erb. W widokach należy unikać stosowania zewnętrznych styli i w ogóle ograniczyć zabawę ze stylami, gdyż w klientach mailowych źle się to wyświetla. Należy raczej pozostać przy dawnym formatowaniu przy pomocy tabel.

Przykładowy plik widoku (powinien być poprzedzony inwokacją doctype, meta, head i innymi, których nie wpisuję, gdyż blogger się burzy):
Tu jest jakiś nagłówek ...................................
<%= @body %>
A tu jest jakaś stopka ...................................
W tym widoku najważniejsza jest zmienna @body, którą definiowaliśmy w metodzie jako :body.
Pozostało już tylko jakoś wywołać tego newslettera. Robię to tak:
UserMailer.deliver_newsletter(newsletter_data, "jan.testowy@test.pl")
W metodzie deliver_newsletter() po podkreślniku występuje nazwa metody, którą klasa UserMailer ma wywołać. Obiekt newsletter_data zawiera w swych polach dane do wysyłki newslettera. Na przykład newsletter_data.subject zawiera temat newslettera.

czwartek, 8 listopada 2012

Różnica pomiędzy delete a destroy w Rails

Najkrócej rzecz ujmując operacja delete wykonuje SQL DELETE z pominięciem wszelkich callbacków w Rails. Jest to więc rozwiązanie szybkie i wydajne.

Jeśli natomiast chcemy aby Rails panowało nad wszystkim zastosujmy destroy. Wolniej ale w zgodzie z wszelkimi regułami pisanej przez nas aplikacji.

Używanie w Rails tekstu typu String zamiast nazwy pola, metody, alboasocjacji

Czasami występuje potrzeba aby w Rails wywołać jakąś asocjację w kodzie ale zamiast standardowego kodu niech nazwy asocjacji będą stringami.

Czyli zamiast pisać tak:
customer=Customer.find(params[:id])
customer.orders.each do |order|
  # ... tu jakieś operacje z użyciem order ....
end

możemy napisać tak:
customer=Customer.find(params[:id])
customer.send("orders").each do |order|
  # ... tu jakieś operacje z użyciem order ....
end

piątek, 21 września 2012

Jak przesłać więcej niż jedną zawartość pola Ajaxem

W Ruby on Rails jest bardzo wygodna pseudokontrolka observe_field. Jednak w swojej podstawowej postaci można przesłać zawartość tylko tego pola, które jest obserwowane. Aby przesłać za jednym razem zawartość większej ilości pól trzeba się trochę pogimnastykować:
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= observe_field "employee_last_name",
            :url => {:action => :nazwa_metody_w_kontrolerze},
            :update => "div_to_update",
            :frequency => 1,
            :with => "Form.serializeElements($('employee_last_name', 'employee_first_name'))" %>
No i jest. Teraz w metodzie nazwa_metody_w_kontrolerze zmienna parameters dostarcza nam imię i nazwisko pracownika w postaci:
params[:employee][:first_name]
params[:employee][:last_name]

czwartek, 15 marca 2012

Mapy tras zgodne z architekturą REST W Rails

Twórcy Ruby on Rails dokonali dużego wysiłku aby się dostosować do architektury REST. Niektórzy określają to jako na wyrost, a inni jako na siłę. Faktem jest jednak to, że dzięki takiemu podejściu powstało wiele udogodnień. Jednym z nich jest unifikacja tras.
Tu szczegóły dla modelu Product:
w pliku routes.rb powstał zapis
map.resources :products
dzięki temu jednemu zapisowi powstała mapa tras:
Metoda Ścieżka Akcja Metoda pomocnicza
GET /products index products_url
GET/products/newnewnew_product_url
POST/productscreateproducts_url
GET/products/1/editeditedit_product_url(:id => 1)
PUT/products/1updateproducts_url(:id => 1)
GET/products/1showproduct_url(:id => 1)
DELETE/products/1destroyproduct_url(:id => 1)

piątek, 9 marca 2012

Warunkowy operator trójargumentowy lub po prostu '?'

Nigdy nie mogę zapamiętać tej składni więc raz na zawsze sobie to tutaj zapiszę.
Zapis
label = length == 1 ? " argument" : " argumenty"
Powyższe wyrażenie przypisuje do zmiennej label łańcuch tekstowy w liczbie pojedynczej lub mnogiej. Oczywiście w zależności od wartości logicznej warunku
length == 1
Jeśli warunek jest prawdziwy to liczba pojedyncza, jeśli warunek jest fałszywy, to liczba mnoga.

piątek, 20 stycznia 2012

Jak wyeleminować duplikaty w tabelach złączeń

W standardowej asocjacji Rails zwanej has_and_belongs_to_many do utworzenia złączenia pomiędzy dwoma tabelami potrzebna jest trzecia tabela z parami kluczy id. Na przykład tabele firms i categories łączy tabela categories_firms. Włożenie do tej tabeli pary kluczy łączy daną firmę z kategorią. Problem w tym, że system dopuszcza wkładanie dowolnej ilości par kluczy. Pomaga w wielu wypadkach zastosowanie zapisu :uniq => true tak jak tu w modelu firm:
has_and_belongs_to_many :categories, :uniq => true
ale niestety nie zawsze.
Aby zabezpieczyć się przed umieszczaniem duplikatów najpierw robimy migrację, która przygotuje unikalny indeks zabezpieczający bazę danych przed zduplikowaniem wpisu:
.
add_index :categories_firms, [ :category_id, :firm_id ], :unique => true, :name => 'unique_by_category_and_firm'
.
Teraz co prawda nie da się zrobić duplikowanego wpisu, ale baza danych wywala błędy.
Przjdźmy więc do modelu firmy i tam dopiszmy do has_and_belongs_to_many:
.
has_and_belongs_to_many :categories, :uniq => true, :before_add => :validates_category
.
czyli zanim dokona się wpisu należałoby wykonać jakąś walidację:
def validates_category(category)
  raise ActiveRecord::Rollback if self.categories.include? category
end

Proste, łatwe i przyjemne.

Inspirację zaczerpnąłem z
http://stackoverflow.com/questions/4988630/habtm-uniqueness-constraint

poniedziałek, 19 grudnia 2011

Jak zamienić string na nazwę klasy

Napotkałem na taki problem: nazwy klas (modeli) mam złożone w postaci zwykłych stringów czyli klasycznych ciągów znaków. Chciałem używać tych stringów jako normalnych klas.

zamiast:
  @employees=Employee.all

użyłem czegoś takiego:
  class_name="Employee"
  @employees=Kernel.const_get(class_name).all

Na pierwszy rzut oka wydaje się to niepotrzebne. Do czasu...

czwartek, 1 grudnia 2011

Dynamiczne dodawanie opcji do kontrolki "select"

Wydawałoby się, że jest to prosta i jakże częsta akcja twórców stron i aplikacji internetowych. Jednak nie udało mi się znaleźć żadnego(sic!) rozwiązania, które byłoby zgodne z duchem Rails. Jak nie ma, to trzeba napisać. Siadłem i popełniłem kod jak poniżej.

Założenia są proste (podam w składni Rails) jest jakaś lista select, na przykład:
<%= select_tag :event_container %>
i chciałbym do tej listy dorzucać pracowników z listy
<%= select_tag(:employee_id,
                options_for_select(Employee.all.map { |employee| [employee.full_name, employee.id] }) %>
Chcę sobie kliknąć na listę z pracownikami, a po kliknięciu zaznaczony pracownik ma "przeskoczyć" z jednej listy na drugą. "Przeskoczyć" to znaczy zniknąć z jednej listy, a pojawić się na drugiej i vice versa.
Do widoku wrzucam więc obserwatory:
<%= observe_field "employee_id",
                   :url => {:action => :move_employee_name},
                   :with => "employee_id" %>
<%= observe_field "event_container",
                   :url => {:action => :remove_employee_from_event},
                   :with => "event_container" %>
i tworzę dla nich pliki RJS odpowiednio: move_employee_name.rjs i remove_employee_from_event.rjs. Muszą one być skorelowane z metodami o takich samych nazwach w kontrolerze! Nie zapomnieć!
Wpisy w move_employee_name.rjs dotyczą oczywiście kontrolek select:
page[:event_container].addNewOption @employee.full_name, @employee.id
page[:employee_id].removeSelectedOption
Wpisy w remove_employee_from_event.rjs są analogiczne
page[:employee_id].addNewOption @employee.full_name, @employee.id
page[:event_container].removeSelectedOption

I tu pytanie za 12 punktów: skąd RJS zna te dziwne metody? Mowa oczywiście o ".addNewOption" i ".removeSelectedOption". I od razu odpowiedź: wpisałem je w /public/javascripts/application.js w postaci:
/* Dodawanie metod do szablonów RJS. */
Element.addMethods({
 /* Dodawanie nowej opcji do kontrolki select. W tym przypadku jest to "element". */
 addNewOption: function(element, option, id) {
  element.options.add(new Option(option, id));
  return element;
 },
 /* Usuwanie zaznaczonej opcji w kontrolce select. Bez parametrów, gdyż funkcja leci po wszystkich. */
 removeSelectedOption: function(element) {
  var i;
  for (i = element.length - 1; i >= 0; i--) {
   if (element.options[i].selected) {
    element.remove(i);
    return;
   }
  }
 }
});
Tam jest właśnie cała magia :-)

Sposób opisany tu przeze mnie jest jak najbardziej zgodny z ideą Rails. Daje się łatwo utrzymać w kodzie aplikacji i jest czytelny. Nic tylko brać!

czwartek, 28 kwietnia 2011

Prosta konfiguracja autocomplete w Ruby on Rails

Znowu walczyłem z autocomplete w Rails. Walczyłem, bo inaczej tego nie można określić.

Twórcą tego pluginu jest osobnik o swojsko brzmiącym nicku dhh. Na stronie poświęconej temu pluginowi można nawet (sic!) natknąć się na przykład jego wykorzystania. Przeglądając tę stronkę trudno coś o niej powiedzieć innego niż "łomatulu!". Wyjaśniać to ona niczego nie wyjaśnia, a tylko denerwuje niedziałającymi linkami scriptacoulosa.

Aby zainstalować z konsoli zawołaj:
ruby script/plugin install auto_complete
oczywiście zazwyczaj nie działa :-(
Można więc ręcznie. Ściągnij zatem plugin i rozpakuj do
/vendor/plugins/auto_complete
zazwyczaj pomaga.

Aby użyć tej kontrolki w widoku wpisz:
<%= text_field_with_auto_complete :model_name, 
                                  :field_in_model_to_search, 
                                  {:value => ""}, {:min_chars => 3, :after_update_element => 'approveForm'} %>
gdzie approveForm jest nazwą funkcji JavaScript, która zostanie wywołana po wybraniu elementu z listy.

Aby rozwikłać pozostałe zawiłości złapałem się po raz kolejny za google i gugłam. Czytam, czytam... i nadziwić się nie mogę. Zerknij tylko (albo raczej nie zerkaj) na railsforum, albo nawet na railscasts. To jakaś masakra jest!

Chodziło mi o prostą rzecz. Chciałem sam zapanować nad zapytaniem do bazy i nad tym co ona zwróci do użytkownika.
Najbardziej zdziwił mnie fakt, że to poniżej działa!!!
class CustomersController < ApplicationController
  auto_complete_for :customer, :name, :conditions => ["gender = ?", "female"]
  .
  .
  .
Zadziałało! Uradowany, nigdzie tego nie wyczytałem, tylko wykombinowałem "na macanta".  Fajno jest. I tak zostało na jakiś czas.
Gdy w następnym miejscu aplikacji znów musiałem czegoś podobnego użyć, miałem prawie gotowe rozwiązanie:
class ProductsController < ApplicationController
  # Nie stosuj tego, to nie działa!
  auto_complete_for :product, :name, :conditions => ["group_id = ?", @group_id]
  .
  .
  .
ale to nie działa. Zmienna egzemplarza pojawia się za wcześnie. Trick z tą zmienną @group_id odpowiadał mi, więc nie chciałem stosować trzymania się prawą ręką za lewe ucho i zacząłem drążyć temat. Po jakimś czasie okazało się, że notacja:
auto_complete_for :product, :name, :conditions => ["group_id = ?", @group_id]
tworzy dynamicznie metodę:
def auto_complete_for_product_name
  .
  .
  .
def
Co wiec stało na przeszkodzie aby taka metodę samemu napisać? Nic, więc napisałem:
def auto_complete_for_product_name
  product_name=params[:product][:name]
  conditions=["name = ? AND group_id = ?", product_name, @group_id]
  @products=Product.all(:conditions => conditions)
end
Sprawdzam... prawie działa.
Prawie bo Rails krzyczy, że brak mu pliku widoku auto_complete_for_product_name.erb
Znów "na macanta" poleciałem. Utworzyłem plik widoku i... zadziałało:
<ul> 
  <% @products.each do |product| %>
    <li><%= h product.name %></li> 
  <% end %> 
</ul> 
Rozwiązanie proste, łatwe i przyjemne.
W kontrolerze panuje się nad każdym przejawem tworzonej listy. Można zrobić dosłownie wszystko czego się tylko zapragnie. Nie trzeba z niczym kombinować jak to pokazywali w sreencaście i proponowali na liście. Moje rozwiązanie jest całkowicie naturalne i w duchu Rails.

Pozostała jeszcze sprawa pozostałych opcji.
Opcje są, a jakże. Żywcem je tu przytaczam:
# Required +options+ are:
# :url:: URL to call for autocompletion results
# in url_for format.
#
# Addtional +options+ are:
# :update:: Specifies the DOM ID of the element whose
# innerHTML should be updated with the autocomplete
# entries returned by the AJAX request.
# Defaults to field_id + '_auto_complete'
# :with:: A JavaScript expression specifying the
# parameters for the XMLHttpRequest. This defaults
# to 'fieldname=value'.
# :frequency:: Determines the time to wait after the last keystroke
# for the AJAX request to be initiated.
# :indicator:: Specifies the DOM ID of an element which will be
# displayed while autocomplete is running.
# :tokens:: A string or an array of strings containing
# separator tokens for tokenized incremental
# autocompletion. Example: :tokens => ',' would
# allow multiple autocompletion entries, separated
# by commas.
# :min_chars:: The minimum number of characters that should be
# in the input field before an Ajax call is made
# to the server.
# :on_hide:: A Javascript expression that is called when the
# autocompletion div is hidden. The expression
# should take two variables: element and update.
# Element is a DOM element for the field, update
# is a DOM element for the div from which the
# innerHTML is replaced.
# :on_show:: Like on_hide, only now the expression is called
# then the div is shown.
# :after_update_element:: A Javascript expression that is called when the
# user has selected one of the proposed values.
# The expression should take two variables: element and value.
# Element is a DOM element for the field, value
# is the value selected by the user.
# :select:: Pick the class of the element from which the value for
# insertion should be extracted. If this is not specified,
# the entire element is used.
# :method:: Specifies the HTTP verb to use when the autocompletion
# request is made. Defaults to POST.

Ogólna notacja kontrolki w widoku jest taka:
.
<%= text_field_with_auto_complete(object, method, tag_options = {}, completion_options = {})  %>
.

Aby na przykład zacząć wyszukiwanie od wpisanych trzech liter kontrolkę skomponuj tak:
.
<%= text_field_with_auto_complete :employee, :name, {}, {:min_chars => 3} %>
.

piątek, 22 kwietnia 2011

count vs length vs size w Rails

W Ruby zarówno #length jak i #size to synonimy podawania wielkości tablicy bądź tablicy asocjacyjnej.
W Railsowym ActiveRecord wygląda na to, że są trzy drogi podawania wielkości asocjacji:
  1. firm.customers.count - wykonuje standardowe zapytanie SQL COUNT. Co ciekawe można podawać warunki podzbioru. Na przykład :conditions => {:customer_name = "Nowak"}. Jeśli nastąpiło wcześniejsze zapytanie SQL COUNT, wtedy #count pokaże zawartość cache, jeśli nie, wykona nowe zapytanie.
  2. firm.customers.length - zawsze ładuje całą asocjację do pamięci, potem ją zlicza i podaje wielkość. Ważne jest, że ta metoda nie wymusza zapytania, jeśli zawartość asocjacji była już pobierana.
  3. firm.customers.size - ta metoda działa w przybliżeniu jako kombinacja dwóch powyższych. Jeśli acocjacja była już pobierana podaje po prostu jej wielkość i tyle. Jeśli nie była pobierana, to wykonuje #count z punktu 1.
Piszę o tym, bo czasami można się naciąć jeśli oczekuje się bardzo szybkiej operacji, a trwa ona zdecydowanie dłużej niż spodziewana. No i to cachowanie...
Więc właśnie. Dwa słowa odnośnie cachowania. Rozważmy następujące przypadki:
Przypadek 1:
@firm = Firm.find(params[:id]) 
@amount_customers_in_firm = @firm.customers.size 
#tu nastąpi zapytanie do bazy

Przypadek 2:
@firm = Firm.find(params[:id])
@customers = @firm.customers 
@amount_customers_in_firm = @firm.customers.size 
#tu zwrócona zostanie ilość rekordów pobrana z cache

Przypadek 3:
@firm = Firm.find(params[:id])
@customers = @firm.customers 
. # tu
. # jakieś
. # gęste
. # operacje
. # na rekordach
@amount_customers_in_firm = @firm.customers(true).size 
#tu wymuszam ponowne zapytanie do bazy z pominięciem cache

Więcej na temat cachowania asocjacji w Rails guides.
Zaś ogólnie o cachowaniu zawodowy artukuł z thewebfellas.


środa, 6 kwietnia 2011

Odcinanie ogonków, czyli zamiana polskich liter w Ruby on Rails

     Napotkałem na problem polegający na tym aby tekst zawierający polskie znaki zamienić na tekst bez polskich znaków. Czyli napis "Łabędź i żółw" ma stać się napisem "Labedz i zolw".
Troszkę poszperałem w sieci, troszkę pokombinowałem i powstał taki kod:
require 'iconv'

class String
  def to_ascii
    ascii = "acelnoszzACELNOSZZ"
    cep = "\271\346\352\263\361\363\234\277\237\245\306\312\243\321\323\214\257\217"
    s = Iconv.new("cp1250", "UTF-8").iconv(self)
    s.tr!(cep, ascii)
    return (s.length==0) ? self : s 
  end
end
     Lubię Ruby za to całkowicie bezkonfliktowe i niezwykle proste wzbogacanie standardowych klas.
Na pierwszy rzut oka pada pytanie: po co sprawdzać długość łańcucha s? Więc to zagadka. Dla wszystkich, którzy zgadną i nadeślą rozwiązanie - nagroda :-)

     Jeśli potrzebujesz takiego rozwiązania to wrzuć powyższy listing do pliku na przykład o nazwie str_utl.rb i umieść w Railsach w katalogu lib, a do pliku environment.rb wstaw require 'str_utl'. U mnie działa to tak:
>> "Łabędź i żółw".to_ascii
>> "Labedz i zolw"


niedziela, 3 kwietnia 2011

Rails autocomplete - uruchamianie akcji po kliknięciu

     Pomiędzy tysiącami dodatków do Ruby on Rails znajduje się kilka, z których korzystamy praktycznie zawsze. Jednym z nich jest "autocomplete". Umożliwia on dynamicznie uzupełnianie zawartości pola tekstowego treścią z bazy danych. Użyteczne, proste w obsłudze i łatwo implementowalne w programie.
Przy czym stwierdzenie "łatwo implementowalne" dałem tak troszkę na wyrost. Pierwsze schody już na samym początku: dokumentacja. Na stronie pluginu otrzymujemy przykład prostej konfiguracji i linki do szczegółowej dokumentacji. Radość? Przedwczesna! Ta prosta konfiguracja opisywana na stronie jest o tyle szybko implementowalna, o ile nigdy nie wystarczająca do Twojego projektu, który akurat piszesz. Natychmiast więc klikasz w linki aby uzyskać szczegóły API, przykłady kodu i inne tego typu, wydawało by się, duperele. Co się okazuje? Linki prowadzą na strony scriptaculous, które nie tylko, że niczego nie rozwiązują, to jeszcze wstydliwie się rozjeżdżają. Jeśli nie wiesz o czym piszę, to kliknij sobie tam na te linki. Wstyd? Mi też się tak wydaje. Nie podaję więc ich tutaj. Podaję zaś link do działającej dokumentacji scriptaculous. Nie pytaj mnie dlaczego tak jest? Nie wiem. Tysiące programistów pytających się o to samo w sieci też nie wie. Cisną się na usta epitety :-) ale nie z takimi rzeczami dawaliśmy radę :-)