Devise User Profile empty fields are shown inside the custom view - ruby-on-rails-3

I want to show a devise user provide inside another view.
Homeprivate/profile.html.erb:
<%= render "devise/registrations/edit" %>
I just converted the default edit view into a partial. To support the user to be available as a "resource", I have the following helper.
module HomeprivateHelper
def resource_name
:user
end
def resource
#resource ||= User.new
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end
end
But if I sign in, and go to /homeprivate/profile -- I see all fields are empty. Somehow the current user is not mapped to the form. How do I map the current user to the profile view if it is displayed in a custom view? Seems like User.new is used, not the current user.

I'm fairly new to rails, but I got the same issue and figured out how to fill those empty fields. In your helper, instead of user.new use current_user. It should look like this:
def resource
#resource ||= current_user
end
That should work.

Related

nested devise user's show path helper

I have nested my controller account which uses a devise user like
resources :venues do
resources :accounts
end
In my accounts controller the index is
before_action :get_venue
def index
#venue
end
def get_venue
#venue = Venue.find(params[:venue_id])
end
I have also tried my index controller as
def index
#venue.users.all
end
I would like to show all the users/accounts for this venue in my view
<%= link_to 'Show Account', venue_accounts_path(user) %>
The generated URL is
/venues/2/accounts
and I would like it to be
/venue/1/accounts/1
Running rails routes I see
venue_account GET /venues/:venue_id/accounts/:id(.:format)
accounts#show
So I assumed that venue_accounts_path(user) will give me /accounts/1/user/1 but that is not what I get.
found it
if it is a nested resource then the helper becomes
venue_account_path(#venue, user)
though I didn't find it in documentation here https://guides.rubyonrails.org/routing.html#nested-resources

Rails - Devise, is it possible to use user_signed_in? without authenticate_user!?

I'm doing a sort of notepad in rails. the main page has this form for notes with the only field "content". Everyone can create a note but I'm trying to add authentication using devise so users can sign up and save their notes.
So I have my site controller with index as uniq method
site controller
def index
#note = Note.new
end
and then a notes controller with the create action
notes controller
def create
#note = if user_signed_in?
current_user.notes.build(params[:note])
else
Note.new(params[:note])
end
respond_to do |format|
if #note.save
format.js
else
format.js
end
end
end
I though that would work but devise helpers only seems to work when I add
before_filter :authenticate_user!
on the controller I need.
is it possible to check if there's a user without the before_filter? or should I make 2 create methods?
As a workaround you can try to add this before filter:
before_filter :authenticate_user!, :only => []
It might add the helpers (if it's really needed) but won't apply to any action.

Cancan allow updating specific attribute of a model

I want to use cancan to allow updating a certain attribute of a model but not others. Here is what my update action looks like.
class UsersController < ApplicationController
load_and_authorize_resource
def update
respond_with User.update(params[:id], params[:user])
end
end
if resource.instance_of? Teacher
can [:read, :update], User do |user|
resource.users.include? user
end
I want Teacher to be able to modify user.course_id but nothing else. How should I change
can :update, User
to do what I want to.
Hm.. I"m not sure if the 'action' in a cancan ability has to explicitly be an action in the controller. If it doesn't, you could do...
# ability.rb
if resource.instance_of? Teacher
can :update_course, User
end
# Controller
def update
params[:user].delete(:course_id) if cannot? :update_course, User
respond_with User.update(params[:id], params[:user])
end

Rails & Devise: How to authenticate specific user?

I'm using Devise for the first time with rails, and I'm having trouble with one thing:
I used the provided authenticate_user! method in my user's controller to restrict access to pages like so:
before_filter :authenticate_user!, :only => [:edit, :show, :update, :create, :destroy]
But this allows any signed in user to access any other users :edit action, which I want to restrict to only that user. How would I do that?
In your edit method, you need to do a check to see if the user owns the record:
def edit
#record = Record.find(params[:id])
if #record.user == current_user
#record.update_attributes(params[:record])
else
redirect_to root_path
end
end
You should look into Authorization such as CanCan. Or alternatively create a new method like so:
# Create an admin boolean column for your user table.
def authenticate_admin!
authenticate_user! and current_user.admin?
end

Where to put business logic that requires the current_user to be known? (Rails)

I have a model (say Car) in which a method needs access to the current_user to determine if the user is allowed to perform the things that the method does.
For example, a method might want to do these things:
Check that current_user owns this object
Check that the object status == 1 (Active)
Check that a related object exists and it's X field is not NULL
I need this business logic to be in the model, not in the controller, so that it's the one place where my business logic will be. The method might get called from places other than a controller.
I know that there are gems like cancan, declarative_authorization etc. but they seem to be overkill for what I need to do. And also, accessing current_user in a model is not considered the "right way".
Then, how do I make that check in the model but still feel "clean"?
I have experienced a situation where "current_user" needs be tightly connected to a model, but I handled it all in the Controller and it works pretty well. Here are some examples:
My model is "Photos". Photos are owned by users, and how people interact with photos is obviously tightly related to whether or not they own the photo.
In the show action I need to load either the existing rating a user has given to a photo (so they can edit it) or allow them to create a new one:
def show
#photo = Photo.find(params[:id])
if user_signed_in?
if #rating = current_user.ratings.find_by_photo_id(params[:id])
#rating
#current_user_rating = #rating.value
else
#rating = current_user.ratings.new
#current_user_rating = "n/a"
end
end
end
When people create photos I want them to be automatically assigned to the current user.
def new
#photo = Photo.new
end
def create
#photo = current_user.photos.create(params[:photo])
if #photo.save
redirect_to user_path(current_user), :notice => t('photo.notice.created')
else
render 'new'
end
end
Only the owners of a photo can change them:
def edit
#photo = Photo.find(params[:id])
if #photo.user == current_user
render 'edit'
else
redirect_to user_path(current_user), :alert => t('application.error.unauthorized')
end
end
def update
#photo = current_user.photos.find_by_id(params[:id])
#photo.update_attributes(params[:photo])
if #photo.save
redirect_to user_path(current_user), :notice => t('photo.notice.updated')
else
render 'edit'
end
end
This approach is based on the constraints that a "current_user" object is tied to the session, which only the controller knows about. So, in short, I have yet to find a good way to integrate "current_user" into a model, but I've been able to find (I think) pretty clean ways to tie the model and controller together so that this can be provided by the controller.
One fairly simple solution to most problems, if your controller is starting to get messy, would be to take a chunk of logic and define as a method in the model, but require one argument = a user object. Then you can just feed "current_user" to that method from your controller and the model handles the rest.
Good luck! Also, if anyone else has any better ideas for this, I'd love to hear them!
Handle auth'ing in a Controller.
Example: Putting auth logic in parent ApplicationController.
class ApplicationController < ActionController::Base
protect_from_forgery
protected
# Returns the currently logged in user or nil if there isn't one
def current_user
return unless session[:user_id]
#current_user ||= User.find_by_id(session[:user_id])
end
# Make current_user available in templates as a helper
helper_method :current_user
# Filter method to enforce a login requirement
# Apply as a before_filter on any controller you want to protect
def authenticate
logged_in? ? true : access_denied
end
# Predicate method to test for a logged in user
def logged_in?
current_user.is_a? User
end
# Make logged_in? available in templates as a helper
helper_method :logged_in?
def access_denied
redirect_to login_path, :notice => "Please log in to continue" and return false
end
end
Now that current_user is an accessor to the logged in user and you can access it in any controller, you can do your authorization logic in the appropriate controller before you do anything with the model.
Your right, though. Models don't care about authorization or who is accessing them.