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.

No_gravatar

Skriv en kommentar her…

6ceb2d2c9e49007bb15fbbb4f580df01?d=http%3a%2f%2fblogg.shortcut.no%2fimages%2fno_gravatar

Fast cash loans are a great idea to get anyone out of short term cash problems.

-

07577d0db242a2da3104cb7048dc1c4c?d=http%3a%2f%2fblogg.shortcut.no%2fimages%2fno_gravatar

What curious question

07577d0db242a2da3104cb7048dc1c4c?d=http%3a%2f%2fblogg.shortcut.no%2fimages%2fno_gravatar

What curious question


Gravatar-aktivert. Les mer om gravatar.
E-postadressen vil ikke vises på siden