Rails-tips: virtuelle attributter
Noen ganger ønsker du å vise felter i et skjema som ikke direkte korresponderer med felter i databasen. Her er et tips på hvordan du kan gjøre dette på en mer elegant måte.
La oss si at du har en modell User som har et for- og etternavn, slik at du kan sortere brukerlistene dine etter for- eller etternavn. Når du viser kunden websida for brukerregistrering protesterer de imidlertid på at det er to felter; det blir for mye tabbing etter deres smak. Du vurderer å migrere dataene dine til å ha et felt for name istedet for de to feltene du har, men det finnes en enklere løsning.
Først lager du to metoder i User-klassen din: en getter og en setter for navn:
class User
def name
[first_name, last_name].join(" ")
end
def name=(a_name)
first, last = a_name.split(' ')
self.first_name = first
self.last_name = last
end
end
Ved å lage disse to metodene ser det ut som users-tabellen din har et name-felt, men det har den ikke – den har to metoder som henholdsvis setter og leser to andre felter i modellen. En ting du kanskje ikke visste er at disse metodene kan brukes i en rekke Rails-metoder, for eksempel slik:
john = User.new(:name => "John Doe") jane.update_attributes(:name => "Jane Doe")
Grunnen til at dette fungerer er måten Rails fungerer på. For hvert nøkkel/verdi-par som sendes inn til disse metodene (new build, update_attributes) kalles metoden som ligger i symbolet med verdien som ligger i verdien. For eksempel a_user.update_attributes(:name => "John Doe") vil metoden name= kalles med parameteret "John Doe". Dette kan du benytte deg av. La oss si at du har en UsersController med en create-action som ser slik ut:
def create
@user = User.new(params[:user])
if @user.save
redirect_to "/"
else
render :action => "new"
end
end
Hvis du har et form som ser slik ut:
<% form_for(@user) do |form| %> <%= form.label :name %> <%= form.text\_field :name %> <%= submit_tag %> <% end %>og du fyller inn “Jon Hansen” i name-feltet, vil disse parametrene sendes inn til
create-action’en din:
user => {:name => "Jon Hansen"}
Dermed vil dette hashet sendes inn som parameter til User.new-action’en i controlleren, og first_name og last_name-feltene vil bli satt slik du ønsker.
Et mer konstruert eksempel kan være om du har en User-klasse og en Mood-klasse. Hver User har et humør (Mood), som representerer et humør denne brukeren har nå; la oss si at du ønsker å kunne finne et humør (Mood.find_by_name 'Tired') og finne alle brukere som har dette humøret. Om du skriver noe som:
class User belongs_to :mood end class Mood has_many :users end
har du en enkel datamodell som støtter dette. Men selv om du nå har en egen modell for alle humørene ønsker du ikke at brukeren må gå inn på en egen side for å lage nye humører, du ønsker bare at brukeren skal kunne skrive inn en tekst i et tekstfelt, og så blir det riktige humøret funnet eller opprettet:
class User
belongs_to :mood
def current_mood
mood.name
end
def current_mood=(a_mood_name)
a_mood = Mood.find_or_create_by_name(a_mood_name)
self.mood = a_mood
end
Du kan nå lage eller hente et Mood-objekt basert på en tekstverdi. Og for å la brukeren skrive inn en tekst på profilsida si for å angi humør kan du bare bruke:
<% form_for(@user) do |form| %> <%= form.label :current_mood %> <%= form.text_field :current_mood %> <% end %>
og du trenger ikke endre en linje i modellen din.

Skriv en kommentar her…
av Navnet ditt..., 14/08-2008
Fast cash loans are a great idea to get anyone out of short term cash problems.
-
av Anonym, 02/11-2010
What curious question
av suzanelyk, 06/02-2012
What curious question
av suzanelyk, 06/02-2012