composed_of - dwa atrybuty, jeden input field

Cześć
W ramach poznawania możliwości RoR, chciałem zrobić prostą (wydawało by się) funkcjonalność.

Member ma swój numer i kartotekę do której jest przypisany. Ani numer, ani kartoteka nie są nigdzie więcej używane, nie są połączone relacjami z Member…

[code]class CreateMembers < ActiveRecord::Migration
def change
create_table :members do |t|
t.string :name
t.integer :number
t.integer :dir

  t.timestamps
end

end
end[/code]

class Member < ActiveRecord::Base composed_of :ident, :mapping => [ %w(number to_s), %w(dir to_s)] end

[code]class Ident < ActiveRecord::Base
attr_reader :number, :dir
def initialize(number, dir)
@number, @dir = number, dir
end

def to_s
[@number, @dir].join("/")
end
end[/code]
Fragment formularza do tworzenia/edycji member

[code]


<%= f.label :ident %>

<%= f.text_field :ident %>
[/code] Działanie tego sprowadza się do utworzenia nowego member, z number i dir zawierających tą samą wartość, tj. dla podanej w formularzu wartości "123/45" zostanie zapisane "123".

Można użyć before_validation i odpowiedniej funkcji, która przekształci przekazany ident i odpowiednio przypisze do number i dir.

Sposób to prosty, ale chyba mało elegancki.

W jaki sposób można to zrobić w modelu, helperze czy może jeszcze gdzieś indziej?

Możesz po prostu w Member zdefiniować metodę przypisania ident:

def ident= (val) self.number, self.dir = val.split('/') end
Na marginesie, jeżeli dobrze rozumiem problem, to klasa Ident niepotrzebnie dziedziczy po ActiveRecord::Base.

Zaiste, dziedziczenie nie jest potrzebne,
Przez ostatnich kilka dni widziałem już tyle sposobów na rozwiązanie tego problemu, że pewnie zostało po którejś kolejnej próbie.

Podany przykład jest tak genialnie prosty, że przez moment nie bardzo wiedziałem dlaczego w ogóle działa :slight_smile:

Dzięki
Pozdrawiam
Tomek