Ruby Forum Rails Germany > Probleme mit Routes bzw. mit RESTful

Posted by Holger Hänisch (ortwin)
on 25.04.2008 21:50
Hallo,

ich benutze Rails 2 mit entsprechender REST Unterstüzung. Leider gibt
meine Literatur dazu nichts her.

Ich möchte in meiner Tabelle hinter einem Feld mit einem Datum ein Link
mit einem Plus Zeichen ausgeben. Der Link soll dann den Datensatz
übernehmen, das Datum um einen Tag erhöhen und dann in die Datenbank
schreiben.

Wenn ich jetzt explizit eine :action => :plus aufrufe geht das nicht.
Verstehe ich ja auch. Passt wohl nicht in die Konvention mit DRY und
REST.

Aber wie löst man denn so ein Problem. Über Routing oder Helper?

Grob beschrieben: Ein Link wird angeklickt, eine Methode aufgerufen die
eine Berechnung durchführt, dann wird der Wert in die Datenbank
geschrieben. Wie setzt man das um?

Danke für die Hilfe.

Holger
Posted by Thomas R. Koll (Guest)
on 25.04.2008 22:20
(Received via mailing list)
Am 25.04.2008 um 21:50 schrieb Holger Hänisch:
>
> ich benutze Rails 2 mit entsprechender REST Unterstüzung. Leider gibt
> meine Literatur dazu nichts her.

API docs!
und quellcode natürlich.


> Wenn ich jetzt explizit eine :action => :plus aufrufe geht das nicht.
> Verstehe ich ja auch. Passt wohl nicht in die Konvention mit DRY und
> REST.
>
> Aber wie löst man denn so ein Problem. Über Routing oder Helper?

Falls sich "geht das nicht" in der Art äußert wie ich's in Erinnerung
hab
dann ist deine Lösung routes:

map.resources :mymodel, :collection => {:plus => :put}

Den Rest weiß die doku, auch was man neben :put noch nehmen kann.

ciao, tom

--
Thomas R. "TomK32" Koll || http://tomk32.de || http://ananasblau.com
just a geek trying to change the world
Skype: TomK32 || Mail: tomk32@gmx.de
Posted by Phillip Oertel (phillipoertel)
on 25.04.2008 23:22
(Received via mailing list)
hi holger,

wenn ich das problem richtig verstehe, möchtest du einen schon
gespeicherten datenbank-eintrag ändern.

wenn du schon eine "map.resources :my_model_name" - regel für das
betreffende model im routing stehen hast, brauchst du dazu weder
zusätzliches routing noch helper -- das geht ganz "restful" mit einem
PUT (der von rails automatisch auf die update-methode des controllers
gemappt wird).

rails macht das mapping, wenn es vom client entweder einen HTTP PUT
bekommt, oder wenn für den parameter "_method" der wert put übergeben
wird. wenn du im template form_for(@my_instance) verwendest, fürgt  
rails den _method - parameter automatisch dem formular hinzu, sonst
ist etwas mehr handarbeit gefordert um den parameter reinzubekommen
(zusätzlicher parameter für form_tag o.ä., oder hidden field).

sorg dann dafür, dass die update-methode beim anklicken des (+) alle
infos bekommt, die sie zum ändern des datensatzes benötigt -- id und
entweder direkt das neue datum, oder eine info um wieviele tage das
datum geändert werden soll.

nachdem du viele werte in einer tabelle stehen hast, könnte button_to
auch hilfreich sein - siehe rails api doku: 
http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#M000914
.

hope this helps!

viele 
grüße,phillip

---

Am 25.04.2008 um 21:50 schrieb Holger Hänisch:
Posted by Holger Hänisch (ortwin)
on 26.04.2008 00:01
Phillip Oertel wrote:
> hi holger,
> 
> wenn ich das problem richtig verstehe, möchtest du einen schon
> gespeicherten datenbank-eintrag ändern.
> 

Nicht ganz. Ich möchte den schon gespeicherten Datenbankeintrag nochmals in 
die Datenbank schreiben, nur soll das Feld Datum einen Tag addiert 
bekommen.

Eintrag:

ID/Datum/Ereignis
50/2008-05-01/Urlaub (+)

ein Klick auf das (+) soll erzeugen:

51/2008-05-02/Urlaub

Hierfür suche ich den "richtigen" Weg. In Rails < 2 würde ich einfach eine Methode 
schreiben die in meinem entsprechenden Controller das erledigt. In Rails 
2 ist das anscheinend nicht so einfach möglich. Ich bekomme es auf jeden 
Fall nicht hin.

Vermutet habe ich aber das ich das über Routing lösen muss. Daher werde ich auf 
jeden Fall den Vorschlag von Tom ausprobieren. Allerding ist das alles 
nicht sehr DRY wie ich das vor habe. Da ich ja in der Methode für (+) fast 
nichts anderes mache als in der Methode create die ich ja sowieso schon 
habe.

Holger
Posted by Phillip Oertel (phillipoertel)
on 26.04.2008 00:08
(Received via mailing list)
achso!

rest-mäßig erstellst du ein neues objekt, also sollte es ein POST auf
die collection des models werden.
lass doch den request auf create gehen, und gib beim klicken dex (+)
die id des zu kopierenden datensatzes mit (z.b. als "create_from_id").
in der create-methode wird dann unterschieden ob die create_from_id
mitkommt, wenn ja wird der datensatz "geklont" und mit geändertem
datum neu gespeichert, wenn nein wird  ein normaler create. dagegen
ist imho nichts einzuwenden.

viele 
grüße,phillip

---

Am 26.04.2008 um 00:01 schrieb Holger Hänisch:
Posted by Thomas R. Koll (Guest)
on 26.04.2008 00:12
(Received via mailing list)
Am 26.04.2008 um 00:07 schrieb Phillip Oertel:
> achso!
>
> rest-mäßig erstellst du ein neues objekt, also sollte es ein POST  
> auf die collection des models werden.
> lass doch den request auf create gehen, und gib beim klicken dex  
> (+) die id des zu kopierenden datensatzes mit (z.b. als  
> "create_from_id"). in der create-methode wird dann unterschieden ob  
> die create_from_id mitkommt, wenn ja wird der datensatz "geklont"  
> und mit geändertem datum neu gespeichert, wenn nein wird  ein  
> normaler create. dagegen ist imho nichts einzuwenden.

Sorry, aber das ist einfach nur dreckiger Code und verwirrt auch
schnell den nächsten Programmierer.

eine zusätzliche Methode lässt sich viel schneller finden und schon
allein vom Namen verstehen.
Man spart ja auch die lästigen Kommentare damit ;-)

ciao, tom


--
Thomas R. "TomK32" Koll || http://tomk32.de || http://ananasblau.com
just a geek trying to change the world
Skype: TomK32 || Mail: tomk32@gmx.de
Posted by Phillip Oertel (phillipoertel)
on 26.04.2008 00:43
(Received via mailing list)
hallo,

Am 26.04.2008 um 00:10 schrieb Thomas R. Koll:

>> und mit geändertem datum neu gespeichert, wenn nein wird  ein  
>> normaler create. dagegen ist imho nichts einzuwenden.
>
> Sorry, aber das ist einfach nur dreckiger Code und verwirrt auch  
> schnell den nächsten Programmierer.

na, noch ganz schon aggressiv um die zeit ...
vorneweg: deine lösung ist ebensogut und wenn man rest mal ausser acht
lässt wäre es wirklich klarer eine separate methode zu machen.
dreckiger code ist aber was anderes.

> eine zusätzliche Methode lässt sich viel schneller finden und schon  
> allein vom Namen verstehen.

map.resources :mymodel, :collection => {:plus => :put} muss auch
erstmal einer finden und verstehen ...

die vorteile meiner lösung sind, dass man nicht am routing schrauben
muss und innerhalb der rest-konventionen bleibt. aber wie schon oben
geschrieben, ich will nicht behaupten, dass das eine besonders schöne 
lösung ist. trotzdem kann man das ganze einigermaßen verständlich
coden (nicht getestet) ...

def create
   new_record_attributes = if params[:create_from_id]
     attributes = MyModel.find(params[:create_from_id]).attributes
     attributes.starts_at = attributes.starts_at + 1.day
     attributes
   else
     params[:my_model]
   end
   MyModel.create!(new_record_attributes)
end


> Man spart ja auch die lästigen Kommentare damit ;-)

??

viele 
grüße,phillip_______________________________________________
rubyonrails-ug mailing list
rubyonrails-ug@headflash.com
http://mailman.headflash.com/mailman/listinfo/rubyonrails-ug
Posted by Stefan Tilkov (Guest)
on 26.04.2008 09:19
(Received via mailing list)
On Apr 26, 2008, at 12:10 AM, Thomas R. Koll wrote:

>> und mit geändertem datum neu gespeichert, wenn nein wird  ein  
>> normaler create. dagegen ist imho nichts einzuwenden.
>
> Sorry, aber das ist einfach nur dreckiger Code und verwirrt auch  
> schnell den nächsten Programmierer.
>


Wieso das? Bei dieser Lösung finde ich den Code zum Erzeugen in
create, d.h. dort, wo ich ihn erwarte. Erscheint mir trotz des if-
statements genau so gültig wir die Fallunterscheidung per routes.rb.

Ist ansonsten wahrscheinlich Geschmackssache. REST-mäßig wäre das Neu-
Anlegen in diesem Kontext auf jeden Fall ein POST, nicht ein PUT.

Viele 
Grüße,Stefan
--
Stefan Tilkov, http://www.innoq.com/blog/st/
Posted by Thomas R. Koll (Guest)
on 26.04.2008 09:35
(Received via mailing list)
Am 26.04.2008 um 00:42 schrieb Phillip Oertel:
>
> Am 26.04.2008 um 00:10 schrieb Thomas R. Koll:
>> Sorry, aber das ist einfach nur dreckiger Code und verwirrt auch  
>> schnell den nächsten Programmierer.
>
> na, noch ganz schon aggressiv um die zeit ...

Tut mir leid, war nich so gemeint, die späte Zeit, Zahnschmerzen und
ZZ Top verwirren das Zentralhirn


>> eine zusätzliche Methode lässt sich viel schneller finden und  
>> schon allein vom Namen verstehen.
>
> map.resources :mymodel, :collection => {:plus => :put} muss auch  
> erstmal einer finden und verstehen ...

übrigens, falls es Holger noch nicht kennt: rake routes

ciao, tom

--
Thomas R. "TomK32" Koll || http://tomk32.de || http://ananasblau.com
just a geek trying to change the world
Skype: TomK32 || Mail: tomk32@gmx.de
Posted by Phillip Oertel (phillipoertel)
on 26.04.2008 11:54
(Received via mailing list)
Am 26.04.2008 um 09:33 schrieb Thomas R. Koll:

> ZZ Top verwirren das Zentralhirn
ok :-)

viele 
grüße,phillip
Posted by Holger Hänisch (ortwin)
on 26.04.2008 20:02
Attachment: tabelle.png (31,4 KB)
Vielen Dank für die Hilfe und die Vorschläge.

Ich habe mich dann auch noch mal in das Thema reingelesen und das 
Tutorial von Wirdemann und Baustert studiert. Die schlage wie Tom für 
mein Problem die Lösung über Routen vor.  Funktioniert auch mit kleinen 
Veränderungen.

routes.rb
map.resources :fehlzeitens, :member => { :plus => :post }, :path_prefix 
=> '/mitarbeiters/:mitarbeiter_id'

ich will das mitarbeiter_id übergeben, weil ich einen before_load Filter 
habe der immer den aktuellen Mitarbeiter einliest.

view:
<td><%= button_to '+', plus_fehlzeiten_path(@mitarbeiter,fehlzeiten), 
:action => 'plus' %>

mit link_to funktioniert es leider nicht. Das führt zu einer sehr 
hässlichen Tabelle. Kann man da noch was machen?

Holger
Posted by Thomas R. Koll (Guest)
on 26.04.2008 21:04
(Received via mailing list)
Am 26.04.2008 um 20:02 schrieb Holger Hänisch:
>
> view:
> <td><%= button_to '+', plus_fehlzeiten_path(@mitarbeiter,fehlzeiten),
> :action => 'plus' %>
>
> mit link_to funktioniert es leider nicht. Das führt zu einer sehr
> hässlichen Tabelle. Kann man da noch was machen?

das schon erwähnte rake routes sagt dir welche helper methoden erzeugt
werden, einfach _path anhängen. Aber wahrscheinlich wird keiner für dich
erzeugt, daher sollte das hier es tun.

button_to '+', {:controller => 'fehlzeiten', :action =>
'plus', :mitarbeiter_id => @mitarbeiter.id, .... }

ciao, tom

--
Thomas R. "TomK32" Koll || http://tomk32.de || http://ananasblau.com
just a geek trying to change the world
Skype: TomK32 || Mail: tomk32@gmx.de
Posted by Holger Hänisch (ortwin)
on 26.04.2008 21:17
Thomas R. Koll wrote:
> Am 26.04.2008 um 20:02 schrieb Holger H䮩sch:
>>
>> view:
>> <td><%= button_to '+', plus_fehlzeiten_path(@mitarbeiter,fehlzeiten),
>> :action => 'plus' %>
>>
>> mit link_to funktioniert es leider nicht. Das f?u einer sehr
>> hä³³lichen Tabelle. Kann man da noch was machen?
> 
> das schon erw䨮te rake routes sagt dir welche helper methoden erzeugt
> werden, einfach _path anhä®§en. Aber wahrscheinlich wird keiner f?h
> erzeugt, daher sollte das hier es tun.

Helper wird erzeugt. Siehe oben: "plus_fehlzeiten_path".

Was mich stört ist die Methode an sich. Also ich meine die Methode 
button_to zu benutzen. Siehe mein Bild. Tabelle wird stark 
auseinandergedehnt. Ein einfacher Link wäre mir da lieber. Da es aber um 
POST geht, wird ja nix übertragen bei einem klick auf einen Link. Gibt 
es dafür eine Lösung?

Holger
Posted by Holger Hänisch (ortwin)
on 27.04.2008 15:11
Geht natürlich doch mit link_to. Einfach :method => :post mitgeben.

Holger