Problem z edycją użytkownika

Poratujcie bo już naprawdę nie wiem o co chodzi. Kontroler:

[code]def edit
@user = User.find(params[:id])
end

def update
@user = User.find(params[:id])

  if @user.update_attributes(params[:user])
    flash[:notice] = 'Konto zostało edytowane.'
  else
    render :action => "edit"
  end

end[/code]
Widok: edit.html.erb [code]<%= error_messages_for :user %>

<% form_for @user do |f| -%>

Login
<%= f.text_field :login %>

Hasło
<%= f.text_field :password %>

Powtórz hasło
<%= f.text_field :password_confirmation %>

<%= submit_tag "Edytuj" -%>

<% end %>[/code]
Wywala błąd: You have a nil object when you didn’t expect it!
The error occurred while evaluating nil.to_sym
@user jest puste. Dałem nawet w kontrolerze helper_method :edit

kiedy wywala błąd? przy akcji edit, czy po wysłaniu formularza?
masz zadeklarowane map.resources :users w routes.rb ?
pokaż error trace, żeby było wiadomo w której linijce się sypie

Wywala się przy akcji edit.

[code]Extracted source (around line #5):

2:
3: <%= error_messages_for :user %>
4:
5: <% form_for @user do |f| -%>
6:
7:
8:

[/code]
I mam zadeklarowane map.resources :users

W API jest napisane, że składnia error_messages_for to

error_messages_for 'user'

Jeśli form_for @user, a nie :user, to musisz to @user najpierw zainicjalizować (choćby i “gołym” rekordem typu User.new). Jeśli nie chcesz inicjalizować, to form_for :user (ale wtedy robisz formularz dodawania nowego, a nie edycji istniejącego użytkownika).

Mam zainicjalizowane @user w edit. Wiec nie wiem czemu nie działa…
Ale jak dodałem ‘:url => users_path’ do <% form_for @user do |f| %> to nie wyświetla juz tego błędu, ale z kolei nie update’uje mi pól w bazie

wg mnie jezeli chcesz aby poszlo do akcji update zgodnie z REST to powinno byc
<% form_for :user, :url => users_path(@user), :html =>{ :method => “put”} do |f| %>

Właśnie, odnośnie dochodzenia do update zgodnie z rest, to ja całe swoje życie pisałem sobie w routes ścieżkę do każdej akcji i tak sobie żyłem w najlepsze.

Ostatnio chciałem zacząć postępowo i wykorzystać to, jak jak Railsy wszystko sobie ładnie rozpoznają. I na moją logikę skoro działa coś takiego:

@user = User.new <% form_for @user do %>
Do utworzenia usera, to również powinno do edycji działać coś takiego:

@user = User.find(costam) <% form_for @user do %>
Chyba railsy powinny się domyślać, że nie robię formularza do akcji show tylko do update, Jednak tak nie było, i musiałem mu jawnie wskazywać akcję update

@user = User.find(costam) <% form_for @user, :url => {:action => "update" } do %>
Dla mnie to nie logiczne. Ale z drugiej strony to skąd user_path ma wiedzieć, że została wywołana w form_for?

@Piotr

http://jarrettcolby.com/articles/3-rest-and-ruby-on-rails-the-big-picture

Nie musi? To form for wywołuje user_path (PUT) lub users_path (POST) w zależności, czy @user.new_record? zwraca false czy true.

najlepiej wpisz to w konsoli

rake routes | grep user

polecam poszukać screencastów o REST.

Dzięki sevos. Czyli działa to tak jak powinno działać w moim mniemaniu, teraz zmieniłem kod i ładnie śmigają testy, nie wiem czemu wcześniej był z tym jakiś problem

Jeżeli robię tak jak napisał lis2, to taki błąd jest: “Only get and post requests are allowed.”
A jeżeli tak jak napisał Piotr Misiurek to taki błąd: “Couldn’t find User with ID=update”

@karol_mur: na początek sprawdź czy masz w miarę świeżą wersję railsów.
Później wygeneruj sobie scaffolda script/generate scaffold FakeUser login:string
przeanalizuj kontroler, widoki i config/routes.rb.
Wydaje mi się, że szybciej znajdziesz problem, niż my tutaj zgadując na forum :slight_smile:

W przykładzie lis2 powinno być:

<% form_for(:user, @user, :url => user_path(@user), :html => { :method => :put}) do |f| %>

ale wg dokumentacji to jest to samo co:

<% form_for(@user) do |f| %>

Niestety nie potrafię w żaden sposób sobie z tym poradzić:/

SPakuj to rar’em, zamieść na jakimś serwerze i daj link. Akurat mi się trochę nudzi to może pomogę … :slight_smile:

Jesteś jeszcze krzyczak? to ci wysle link do rara

Jeszcze jestem :slight_smile:

Badałem problem kolegi i wyszło na to, że jak zmienię w kontrolerze, w metodzie update, ten fragment:

@user = User.find(params[:id]) if @user.update_attributes(params[:user]) flash[:notice] = 'Konto zostało edytowane.' redirect_to(@user) else render :action => "edit" end
na taki

@user = User.find(params[:id]) if @user.update_attributes(params[:user]) flash[:notice] = 'Konto zostało edytowane.' redirect_to(:controller => 'users', :action => 'show', :id => @user) else render :action => "edit" end
czyli zmiana redirect_to(@user) na redirect_to(:controller => ‘users’, :action => ‘show’, :id => @user)

Dodatkowo w widoku edit.html.erb trzeba było zmienić
<% form_for(@user) do |f| %>

na

<% form_for @user, :url => {:action => “update”, :id => @user.id } do |f| %>

Ktoś ma pomysł dla czego tak jest? To jest bez sensu, że jak jest redirect_to(@user) to wali exceptionem a jeśli wpiszę podaną linijkę to poprawny url konstruuje.

I czemu w formularzu musi być cały ten :url skoro dla scaffolda działa poprawnie edycja bez tego parametru?

Ciekawi mnie dla czego tak się dzieje. Ktoś ma jakieś wyjaśnienie?

a masz cos takiego w routes’ach ??

map.resources :users

jak robisz scaffolda to cos takiego sie dodaje :wink:

A no właśnie o to chodzi, że to jest :slight_smile:
Najgorsze jest to, że jeżeli zrobię scaffolda, np. script/generate scaffold TestUser name:string to wszystko jest ok. Działa jak ma działać. Natomiast na tym modelu User, który jest już w tej aplikacji zrobiony, mając w routes.rb wpis map.resorces :users nie działa formularz edycji bez tego dodatkowego parametru :url oraz w kontrolerze musi być redirect_to ze wszystkimi parametrami bo redirect_to(@user) nie działa. I nie mam pojęcia dla czego się tak dzieje…

to zapodajcie jakims linkiem

popatrze :wink: