Formularz :name na :id

Cześć. Mam problem z zamiana nazwy na id pewnego recordu.
Sprawa wygląda tak, mam model Favourite który posiada kolumne station_id (relacja has_one).
W formularzu tworzenia Favourite mam pole w którym należy podać nazwe stacji. Pytanie jak powinienem zrobić zmiane z nazwy na id stacji, w bazie danych id to integer wiec w formularzu też jest oczekiwany integer. Próbowałem takiej walidacji:

def validate_station_exist unless self.station_id = Station.find_by_name(self.station_id.to_s.upcase).try(:id) errors.add :station_id, 'Przystanek odjazdowy nie istnieje.' end end
lecz to nie działa tak jakbym chciał.

w tą stronę powinieneś iść i szukać:

np:
validates_associated :manufacturer
validates_presence_of :manufacturer_id

No i ta twoja validacja nie ma sensu, masz coś takiego

def aaa
id = …find_by_name(id)
end

jak to ma działać? Chcesz szukać po nazwie, a dajesz id?

Napisz dokładnie co chcesz uzyskać. Czy chodzi Ci o to, żeby można było w formularzu wybrać stację i ustawić ją jako domyślą? Czy może Twoim celem jest uczynienie z :name klucza głównego w tablicy?
Ad. 1 - typowa sytuacja, trzeb tylko odpowiednio przygotować argument dla select-a (tablica par “nazwa - id”)
Ad. 2 - nie tędy droga

Chcę uzyskać formularz dla modelu Favourite w którym będzie pole station_id. W tym polu użytkownik podaje nazwe stacji (czyli jest to string), nie może to być select, normalny text_field. Chciałbym w kontrolerze/modelu coś co by mi zamieniło tą nazwe na id tej stacji.

Chodzi o Station.find_by_name(params[:station_name]).id czy coś bardziej wyrafinowanego?

Dokładnie tylko, że w bazie danych ta kolumna jest integerem a z formularza dostane stringa.

#4xup

To jest tylko pole w którym początkowo dostaje stringa z nazwą. To ma zamienić tego stringa na konkretne ID stacji.

Troche kodu może bardziej zaobrazuje mój problem:

[code]#widok
= f.label :station_from_id, ‘Z’
= f.text_field :station_from_id,
:autocomplete => search_schedule_autocomplete_station_name_path

= f.label :station_to_id, ‘Do’
= f.text_field :station_to_id,
:autocomplete => search_schedule_autocomplete_station_name_path

#kontroler
def create
@favourite = Favourite.new(params[:favourite])
if @favourite.save
redirect_to favourites_url
else
flash[:errors] = @favourite.errors
render :action => pages_errors_path
end
end

#model
def validate_station_from_exist
unless self.station_from_id = Station.find_by_name(self.station_from_id.to_s.upcase).try(:id)
errors.add :station_from_id, ‘Przystanek odjazdowy nie istnieje.’
end
end

def validate_station_to_exist
  unless self.station_to_id = Station.find_by_name(self.station_to_id.to_s.upcase).try(:id) 
    errors.add :station_to_id, 'Przystanek docelowy nie istnieje.'
  end
end

#troche schemy
create_table “favourites”, :force => true do |t|
t.datetime “created_at”
t.datetime “updated_at”
t.integer “station_from_id”
t.integer “station_to_id”
t.string “name”
t.boolean “on_start_page”
end[/code]

No dokładnie musisz zrobić tak jak wyżej już pisze

Ktoś wpisuje ci nazwe, klika zapisz, szukasz to tej nazwie (tak jak u góry) zwraszasz ID wyszukanego obietu i masz id, jest w bazie (sprawdzasz) puszczasz, nie ma wracasz

PS
Źle to robisz, co z literówkami, odmianami i innymi dziwnymi zachowaniami userów które będą pisać. Czemu nie select? Jak i tak nie chcesz puszczać bez ważnego ID, a może chodzi ci o find_or_create, czyli jak nie ma to tworzy? Ale to znowy zły pomysł, literówki itp

#up
Text_field dlatego, że aplikacja jest kiedrowana na iphona, androida. Wyświetlanie selecta z ponad 300 recordami będzie ciężarnią dla użykownika.

Ta walidacja mi nie działa, dlatego pytam jak się robi takie przemianowanie railsowym sposobem.

def validate_station_to_exist unless self.station_to_id = Station.find_by_name(self.station_to_id.to_s.upcase).try(:id) errors.add :station_to_id, 'Przystanek docelowy nie istnieje.' end
Nie powinno być czasem podwójne równa się w warunkach? -> ==

W tym wypadku to moim zdaniem najlepiej skorzystać z live searcha i w ukrytym polu zapisać id wybranego obiektu.

+1

[code=ruby]class Favorite
attr_accessor :station_name
before_validation :fetch_station

def fetch_station
self.station = Station.find_by_name(station_name) if station_name
end
end[/code]
W widoku:

= f.text_field :station_name

Podobne rozwiązanie działa zacnie i bez Javascript/Live search - co najwyżej musisz rozbudować metodę Station.find_by_name tak, żeby dawała sobie radę z niedokładnie podanymi nazwami stacji.