In my rails app, if I go to localhost:3000/users/edit to update user
<h2>Edit <%= resource_name.to_s.humanize %></h2>
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.text_field :email%></div>
<div><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password, :autocomplete => "off" %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %></div>
<div><%= f.submit "Update" %></div>
<% end %>
<h3>Cancel my account</h3>
<p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), :data => { :confirm => "Are you sure?" }, :method => :delete %></p>
<%= link_to "Back", :back %>
It 's alright, but if I move this code ((or render this view) to another view of another controller it 'll have an error :"undefined local variable or method `resource' for #<#:0x3b27478>"
I don't know how to fix it, any help really appreciated.
resource is a variable set by the Devise gem. In order to move the above code somewhere else, it means that you will have to take care of setting the resource variable yourself.
Basically a rails form_for wants to take the instance of the object you want to create / edit.
<%= form_for instance_object ...
In your case you'll need to first fetch the user you want to edit (or use current_user) and then give it to the form_for helper method:
<%= form_for current_user ...
or by setting the #user instance variable in your controller first:
def new
#user = User.new
end
def edit
#user = User.find(some_id)
end
Then in your view:
<%= form_for #user ...
Don't forget to replace all the resource occurences by your instance variable.
Related
I'm new to Rails.
I have a register page in my app. Also a profile page. I'm trying to make an edit page where I can edit users email, password and all. I want to do all this using devise..
I have reached so far. here is my edit page.
<div class="edit_profile_page">
<%= form_for(current_user, :url => '/update', :html => { :method => :put }) do |f| %>
<div><%= f.label :email %><br />
<%= f.email_field :email, :autofocus => true %></div>
<div><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password, :autocomplete => "off" %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %></div>
<div><%= f.submit "Update" %></div>
<% end %>
</div>
I'm stuck here. What url should i pass.. Also if this url points to a method say
def update_profile
end
what should i write inside that method so that the password will get updated like the one happened while registration.
Or
There is an edit page inside Device. How should i write my routes to reach there.
You can also create own ProfilesController, example below:
Routes:
#routes.rb
resource :profile
Controller:
# coding: utf-8
class ProfilesController < ApplicationController
before_filter :authenticate_user!
def show
#user=current_user
#user.email = nil unless #user.email.scan('#example.com').empty?
render 'devise/profile/edit'
end
def update
#user=current_user
if #user.update_attributes(params[:user])
sign_in 'user', #user, :bypass => true
flash[:notice] = t('users.profile.edit.updated')
respond_to do |format|
format.html { redirect_to '/'}
end
else
render 'devise/profile/edit'
end
end
end
Views
#views/devise/profile/edit.html.haml
%h3
= t('users.profile.basic_settings')
= simple_form_for #user, :url => profile_path, :html => { :method => :put } do |f|
-#= f.error_messages
= f.input :name, :placeholder=>t('activerecord.placeholders.name')
= f.input :email, :placeholder=>t('activerecord.placeholders.email')
= f.submit t('users.profile.change_name'), :class => "btn btn-primary"
= t('users.profile.change_password')
= simple_form_for #user, :url => profile_path, :html => { :method => :put } do |f|
-#= f.error_messages
= f.input :password , :error_html => { :id => "password_error"}
= f.input :password_confirmation
= f.submit t('users.profile.change_password'), :class => "btn btn-primary"
I use devise_security_extension in order to have some password security features in my app.
I use password_expirable in one of my models, and when the password expires it goes to this view and I find no way to edit its content. Do you have any suggestion how I can control this view's HTML?
Currently, the gem will not automatically generate the view for you to edit. I think it's one of the things that people have asked for. In the meantime, you can manually create the file. If you look in the gem's:
devise_security_extension/app/views/devise/password_expired/show.html.erb
You'll see the current template for the view that the gem uses. Copy and paste this file into your views/devise/password_expired/show.html.erb
You'll then be able to edit it the way you'd like.
The file looks like this:
<h2>Renew your password</h2>
<%= form_for(resource, :as => resource_name, :url => [resource_name, :password_expired], :html => { :method => :put }) do |f| %>
<%= devise_error_messages! %>
<p><%= f.label :current_password, "Current password" %><br />
<%= f.password_field :current_password %></p>
<p><%= f.label :password, "New password" %><br />
<%= f.password_field :password %></p>
<p><%= f.label :password_confirmation, "Confirm new password" %><br />
<%= f.password_field :password_confirmation %></p>
<p><%= f.submit "Change my password" %></p>
<% end %>
I have a devise users table with a fully functioning sign in/up form.
What I was wondering was how to have that users form appear on a different table.
For example
users/sign_in works perfectly
but
I want to have that form appear on movies/index
Ive tried adding the form code to the movies/index but i get this error
undefined local variable or method `resource' for #<#<Class:0x00000102cbf0b8>:0x00000103bb6d78>
This is the sign in form
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
<div><%= f.label :email %>
<%= f.email_field :email, :autofocus => true %></div>
<div><%= f.label :password %>
<%= f.password_field :password %></div>
<% if devise_mapping.rememberable? -%>
<div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
<% end -%>
<div><%= f.submit "Sign in" %></div>
<% end %>
<%= render "devise/shared/links" %>
Thanks!
You can generate the views (I understand you already did that) and you can override the controllers, or, in your case, you can watch the controllers of Devise, take the code that you need, and in your view call a partial (from the Devise views).
I did something like that a few months ago, but what I did (that I don't fully suggest but I haven't find a better way) was to take the code from the Devise views, and copy the code in another view with some modifications:
<%= form_for(User.new, :as => "user", :url => session_path("user"), :remote => true) do |f| %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
<div><%= f.submit "Sign in" , :class=>"blue_submit_degradiant", :id =>"sign_in_user"%></div>
<% end %>
It works, but the right way is to have a #user instead of User.new
I am using the Devise authentication gem for a Ruby on Rails app. When a user logs in by creating a new session I would like to update a column in my user model. What would be the best way to do this?
Is there any way to have a hidden field that updates the model?
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<% if devise_mapping.rememberable? -%>
<div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
<% end -%>
<% f.hidden_field :field_a, :value => 'test' %>
<div><%= f.submit "Sign in" %></div>
<% end %>
You can do this by overwriting Devise::SessionsController create method. When the user login it will just authenticate the user, it wont update user record. So there is no use of keeping the hidden field in the form
Try like this
class Users::SessionsController < Devise::SessionsController
def create
#do your update here
end
end
or else you can follow this link http://denmarkin.tumblr.com/post/5194645960/how-to-overwrite-devise-sessions-controller-in-rails-3
<%-roles = Role.all%>
<%= panel "Edit" do%>
<%= semantic_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
<%= f.error_messages %>
<% f.inputs do %>
<p><%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password %></p>
<p><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></p>
<p><%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password %></p>
<%=f.input :roles,:collection => Role.all%>
<% end %>
<% f.buttons do %>
<%=f.submit "Update" %></p>
<% end %>
In here, when I don't type any password in, the error message shows but also the role of the user gets changed as well. How do I make it so that the role doesn't change?
The user's role changes are in memory, no in database. You can do model.reload to discard memory changes and reload your user from database if a validation error happens.