Devise - crud nie działa

Używam devise i chciałbym zrobić możliwość modyfikowania przez administratora danych personalnych dowolnego użytkownika(czyli akcje: index, show, edit, update, destroy).

route.rb

[code=ruby] devise_for :users, :path_names => { :sign_up => “register”,
:sign_in => “login”, :sign_out => “logout” }

namespace :admin do resources :users, :except => [:new, :create] end[/code]
admin/index.html.erb

[code=ruby]<% title “Listing users” %>

<% for admin_user in @admin_users %>
</tr>

<% end %>

Email
<%= admin_user.email %> <%= link_to "Show", admin_user_path(admin_user) %> <%= link_to "Edit", edit_admin_user_path(admin_user) %> <%= link_to 'Destroy', admin_user_path(admin_user), :confirm => 'Are you sure?', :method => :delete %>
[/code] show.html.erb [code=ruby]<% title "Listing admin_users" %>

Email: <%= @admin_user.email %>

<%= link_to "Edit", edit_admin_user_path(@admin_user) %> | <%= link_to "Destroy", :controller => "admin/users", :action => "destroy", :id => @admin_user %> | <%= link_to "View All", admin_users_path %>

[/code] Niestety po wywołaniu akcji destroy albo edit(w scieżce /admin/users/) mam komunikat:

Parametry w user.rb:

devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable

O komunikacie przeczytasz tutaj: http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf

Wrzuć wyjście rake routes, zobaczymy dokąd akcja edit prowadzi.

routes.rb

new_user_session GET /users/login(.:format) {:action=>"new", :controller=>"devise/sessions"} user_session POST /users/login(.:format) {:action=>"create", :controller=>"devise/sessions"} destroy_user_session GET /users/logout(.:format) {:action=>"destroy", :controller=>"devise/sessions"} user_password POST /users/password(.:format) {:action=>"create", :controller=>"devise/passwords"} new_user_password GET /users/password/new(.:format) {:action=>"new", :controller=>"devise/passwords"} edit_user_password GET /users/password/edit(.:format) {:action=>"edit", :controller=>"devise/passwords"} PUT /users/password(.:format) {:action=>"update", :controller=>"devise/passwords"} user_registration POST /users(.:format) {:action=>"create", :controller=>"devise/registrations"} new_user_registration GET /users/register(.:format) {:action=>"new", :controller=>"devise/registrations"} edit_user_registration GET /users/edit(.:format) {:action=>"edit", :controller=>"devise/registrations"} PUT /users(.:format) {:action=>"update", :controller=>"devise/registrations"} DELETE /users(.:format) {:action=>"destroy", :controller=>"devise/registrations"} admin_users GET /admin/users(.:format) {:action=>"index", :controller=>"admin/users"} edit_admin_user GET /admin/users/:id/edit(.:format) {:action=>"edit", :controller=>"admin/users"} admin_user GET /admin/users/:id(.:format) {:action=>"show", :controller=>"admin/users"} PUT /admin/users/:id(.:format) {:action=>"update", :controller=>"admin/users"} DELETE /admin/users/:id(.:format) {:action=>"destroy", :controller=>"admin/users"} main_index GET /main/index(.:format) {:controller=>"main", :action=>"index"} root /(.:format) {:controller=>"main", :action=>"index"}

a metode gdzie masz w destroy ?

chyba bardziej powinno to wyglądać jakoś takoś nie?
<%= link_to “Usuń”, admin_user_path(user), :method => :delete, :confirm => “Usunac?”%>

[quote=czACha]chyba bardziej powinno to wyglądać jakoś takoś nie?
<%= link_to “Usuń”, admin_user_path(user), :method => :delete, :confirm => “Usunac?”%>[/quote]
W show.html.erb miałem stary kod. Usuwam aktualnie poprzez index.html.erb a tam jest:

     <td><%= link_to 'Destroy', admin_user_path(admin_user), :confirm => 'Are you sure?', :method => :delete %></td>

Więc jest to samo co zapodałeś.
Wynik taki sam.

Wygląda na to, że Edit powinno działać, jesteś pewien że nie masz na myśli problemu z #update?

Link do akcji Destroy powinien wyglądać tak:

<%= link_to "Destroy", admin_user_path(@admin_user), :method => :delete %>

Tak edit działa. :slight_smile: Po prostu się pomyliłem z nazwą akcji.

Jednak przy naciśnięciu update w edit.html.erb mam komunikat:

[code=ruby]Routing Error

No route matches “/admin/users/2/edit”[/code]
Czyli źle zrobiony jest routing.

Co ciekawe jeśli chcę wykonać edycje profilu poprzez /users/edit (to będzie devise’owy kontroler /devise/registrations) to wtedy działa i zmienia dane profilu.

Podejrzewam że po prostu devise jakoś blokuje zmiany bo kod jak dla mnie wygląda dobrze(chodzi mi o index.html.erb).

Formularz edycji powinien być wysyłany metodą PUT do admin_user_path, a obecnie jest wysyłany do edit_admin_user_path.

chyba POST

Dodałem regułkę w routes.rb

[code=ruby] devise_for :users, :path_names => { :sign_up => “register”,
:sign_in => “login”, :sign_out => “logout” }

namespace :admin do
resources :users, :except => [:new, :create]
put “/users/:id”, :to => “users#update”, :as => :user_update
end[/code]
rake routes:

new_user_session GET /users/login(.:format) {:action=>"new", :controller=>"devise/sessions"} user_session POST /users/login(.:format) {:action=>"create", :controller=>"devise/sessions"} destroy_user_session GET /users/logout(.:format) {:action=>"destroy", :controller=>"devise/sessions"} user_password POST /users/password(.:format) {:action=>"create", :controller=>"devise/passwords"} new_user_password GET /users/password/new(.:format) {:action=>"new", :controller=>"devise/passwords"} edit_user_password GET /users/password/edit(.:format) {:action=>"edit", :controller=>"devise/passwords"} PUT /users/password(.:format) {:action=>"update", :controller=>"devise/passwords"} user_registration POST /users(.:format) {:action=>"create", :controller=>"devise/registrations"} new_user_registration GET /users/register(.:format) {:action=>"new", :controller=>"devise/registrations"} edit_user_registration GET /users/edit(.:format) {:action=>"edit", :controller=>"devise/registrations"} PUT /users(.:format) {:action=>"update", :controller=>"devise/registrations"} DELETE /users(.:format) {:action=>"destroy", :controller=>"devise/registrations"} admin_users GET /admin/users(.:format) {:action=>"index", :controller=>"admin/users"} edit_admin_user GET /admin/users/:id/edit(.:format) {:action=>"edit", :controller=>"admin/users"} admin_user GET /admin/users/:id(.:format) {:action=>"show", :controller=>"admin/users"} PUT /admin/users/:id(.:format) {:action=>"update", :controller=>"admin/users"} DELETE /admin/users/:id(.:format) {:action=>"destroy", :controller=>"admin/users"} admin_user_update PUT /admin/users/:id(.:format) {:controller=>"admin/users", :action=>"update"}
_form.html.erb

[code=ruby]<%= form_for admin_user_update_path(@admin_user) do |f| %>
<% if @admin_user.errors.any? %>


<%= pluralize(@admin_user.errors.count, “error”) %> prohibited this admin_user from being saved:

  <ul>
  <% @admin_user.errors.full_messages.each do |msg| %>
    <li><%= msg %></li>
  <% end %>
  </ul>
</div>

<% end %>

<%= f.label :name %>
<%= f.text_field :name %>

<%= f.submit %>

<% end %>[/code] Ale nadal błąd: [code=ruby]Routing Error

No route matches “/admin/users/2/edit”[/code]
Edycja:
Tak z ciekawości badałem też inne CRUDy w moim projekcie i coś nie bangla destroy nigdzie.
Mogę wszędzie robić(poza admin/users) nowy rekord, wyświetlać go, modyfikować, natomiast destroy zawszę wywala ten sam błąd:

ActionController::InvalidAuthenticityToken

Jeśli REST to #update powinien iść przez PUT.

@Matthias powinno wystarczyć

<%= form_for [:admin, @admin_user] do |f| %>

Poczytaj http://guides.rubyonrails.org/form_helpers.html i http://guides.rubyonrails.org/routing.html, a i resztę też nie zaszkodzi. :slight_smile:

Dodam tylko że scaffold robiłem poprzez nifty_generators(wszystko poza admin/users; nifty-generator nie działa dobrze dla wywołania “katalog/kontroler”, dodaje bez sensu “/” do większości plików)

gem 'nifty-generators', '0.4.2'

aaa przepraszać myślałem że rozmowa była o create ups sory najmocniej

Dobra destroy już działa. Brakowało

<%= csrf_meta_tag %>

w application.html.erb

[quote=hekto5]@Matthias powinno wystarczyć

<%= form_for [:admin, @admin_user] do |f| %>

[/quote]
Niestety nie działało.

Zauważyłem że jak załadujesz moduł :registrable w Devise to nie działa wtedy CRUD(nawet nie działa modyfikacja, jeśli jest kod dobrze). Z kolei jak go wyłączysz to nie masz rejestracji otwartej ale wszystkie akcje działają.

Ale w sumie poradziłem sobie z grubsza.
Skorzystałem z tutoriala tego pana:
http://www.tonyamoyal.com/2010/07/28/rails-authentication-with-devise-and-cancan-customizing-devise-controllers/
http://www.tonyamoyal.com/2010/09/29/rails-authentication-with-devise-and-cancan-part-2-restful-resources-for-administrators/
HABTM skorzystałem z:

CRUD bangla po tym tutorialu.
Tylko coś to habtm_checkboxes nie zapisuje do bazy danych jak zahaczę dodatkowe role.

Dobrze że działa. :slight_smile:

Dobra tego habtm też rozgryzłem. Dziękuje za pomoc.
Temat do zamknięcia.