Rails 4 and Devise: add custom var at current_user - ruby-on-rails

How can i customize current_user adding an attribute like current_user.array ?
EDIT: better explaination
I need to save the records ids of an associated table cause i dont wanna call the db every time a user visit a page like products/1 to control if the product is associated at the current_user. With the ids i can do something like if the array stored in session[:ids] contain params[:id] current_user can access to the page else redirect_to root_path

current_user is just a Devise helper for the attributes of the currently signed-in user
Adding extra attributes to the object this helper represents will have to be done through the User model:
#app/models/user.rb
Class User < ActiveRecord::Base
has_one :profile
end
#-> current_user.profile.image

In devise current_user refers to the user currently logged in. By using current_user.something you can access the value stored in something. something could be a column in the user table or simply an attribute in the model for storing values.
If you want to store some values for the user only as long as the user is logged in, you can store it in session by using
session[:something] = #Value of something
You can access this value by using session[:something].

Why do you use the session? It is already associated with the current user. For example
Try this in your controller:
session[:array] = #something...

just add the attribute to your user model

You can access the columns in th users table using current_user, but the attributes must be accessible.
current_user.name where name is in the users table and it is attr_accessible in User.rb

Related

Rails 5 - Best way to hold onto params for creating associations?

Here's the scenario to illustrate my question. I have 2 models:
# models/post.rb
belongs_to :user
validates_presence_of :comment
And we have a devise model called Users
# models/user.rb
has_many :posts
What I would like to achieve:
Person comes to the website, is able to create a Post, after creating the Post, they are prompted to create an account. After creating the account, the Post that they just created would be associated to the User they just created.
Usually i'd make use of routes to hold the params[:id] which can be accessed in the controller method. For example the URL may look something like this:
www.foo.com/foo/new/1
And then I can do this:
# foo_controller.rb
def new
#foo = Foo.new
#parent = Parent.find(params[:id])
end
And in the view I can simply access #parent and use a hidden field to fill the parent ID.
But when routing through so many different pages (such as creating a Devise User), how do I hold onto the parent/child ID such that I can still create that association?
Using an hidden field or the route to store the id, with no authorization in the process, would not be secure. What if I just use the browser inspector and change the value of the id ? Your cool post would be mine.
What you could do is, for instance, add a field called guest_id to the Post, in which the value is unique (like SecureRandom.uuid), and also store that value in the session.
Thus, after the user is created, you could do something like that
if (post = Post.find_by(guest_id: session[:guest_id])).present?
post.update(user_id: current_user.id)
end

Create User Account Settings Page in Ruby on Rails with devise

I am new to Ruby on Rails and I have created a project that contains a User table (generated by devise) and a AccountSetting table that contains user specific account settings (this table has a foreign key that relates to the id in the User table thus each User has zero or one AccountSettings). I have my seed data working fine, and I can seed the database with users that have user specific account settings. The User table is related to the AccountSetting table with a "has_one :accountsetting" and the AccountSettings table "belongs_to :user". This all works and makes sense. However, I have a method called "show_user_setting" in my UserSettings controller, and I do not know how to ONLY SHOW the account settings for that specific authenticated user.
So, how can I only display the user setting for the currently logged in user? Again, I am using devise.
My general idea of how to do this would be something like this. However I know this is incorrect, but for the purpose of an explanation, here it is.
def show_user_setting
#setting = AccountSetting.find(current_user)
end
My idea is that the #setting will contain the setting for the currently logged in user. Thanks in advance!
You should do this:
#app/models/account_setting.rb
class AccountSetting < ActiveRecord::Base
belongs_to :user
end
#app/models/user.rb
class User < ActiveRecord::Base
has_one :account_setting
end
This will allow you to call the following:
#setting = current_user.account_setting
Our Setup
For what it's worth, we do something similar:
#app/models/user.rb
class User < ActiveRecord::Base
before_create :build_profile #-> builds a blank profile on user create
has_one :profile
end
#app/models/profile.rb
class Profile < ActiveRecord::Base
belongs_to :user
end
This allows us to put all sorts of different options inside the profile model (we have homepage etc):
The important thing to note here is that the above allows you to delegate various methods to the profile model, allowing you to call the following:
current_user.profile_name
current_user.profile_signin_redirect?
current_user.profile_avatar
etc
Have you tried
def show_user_setting
#setting = AccountSetting.find_by(user_id: current_user.id)
end
The way .find() works is it searches the model for the id passed. So, the way you currently have it is your going to try to search for the id of the model, when you want to find the foreign key. So use Model.find_by(column_name: param). You'll what to change user_id: to the column name of what you're storing the foreign key in, I'm just assuming it's something similar to that.
I'm guessing the show_user_setting function is part of a controller, if it is on a model then read this: accessing devise current_user within model
to set the #setting variable you should be able to do this
#setting = AccountSetting.find(user_id: current_user.id)
or
#setting = AccountSetting.find(user: current_user)

Rails_admin, Assigning Devise's current_user to model inside action

I have Devise Model Person which will log in and manage rails_admin app.
I have model called Model which has updater that was added by mongoid-history.
In order to set who updated my story I need to do something like this:
model = Model.new
model.updater = Person.first
model.save
According to this link to github, I can not set current_person, which created by Devise automatically. That's means that I need to set updater manually each time when something happens to my Model.
How to get current_person and set it to Model where rails_admin's action happens?
I only know that I need to write something to each action in initializers/rails_admin.rb
There's no access to current_user from the Model, because ActiveRecord models can be used independently from Rails apps, they can be used without logging in.
It is the controller that (often) requires the user to login and so has access to the user session and the current_user method. The controller must therefore do the work of setting the updater on the Model.
Perhaps you could set a callback method in the controller that acts on any action that modifies the model and sets the updater there.
I have found one solution for my question, but I don't know if it is good aproach or not.
If I want to assign my current_person in edit action I needed to write this:
config.model Model do
edit do
field :updater_id, :hidden do
visible true
def value
bindings[:view]._current_user.id
end
end
end
end
It createds hidden field which has asigned ID of current person which is logged in.
Mr.D's answer seems not to work (at least as of rails_admin 2.0.2); bindings doesn't have a :view key. The correct key is now :controller:
bindings[:controller].current_user # returns current User object
And if you not have a attribute to store this id and just need id to validate another operation, you can create a attribute to it:
config.model Model do
edit do
field :updater_id, :hidden do
visible true
def value
bindings[:view]._current_user.id
end
end
end
end
MODEL:
class TaxPlan < ApplicationRecord
attr_accessor :updater_id
validate :validate_updater_id
def validate_updater_id
yor code validation here
end
end

how can I create a form for User model which can be updated after successfully logged into application

Requirement: I need to create an application where user can logged in and can change the background color of that page, can change the font of the page and it should persist with session. so I am trying to create form which accept those attributes from user and can save in database. I am using devise for authentication.
How can I create form for user who is successfully logged into application(authentication is done by devise gem, so user table is already existing) and upon submission of form those attributes should get updated in user table. Any suggestion will be appreciated.
Q1 .What should be the name of controller and view for this form ?
Q2. How the routes can be define.
Q3. Whether controller should have update action to update user table with the extra attributes present in the form.
Thanks. Please comment below if I missed some information needed to provide. You can suggest me if you think this can be achieve in easier way also.
Whatever you want. Sounds li?ke you are just updated user attributes, so i would just use the User#update action
resources :users, only: [:update, :edit] #and any other user routes
? see 1
Also you will want to make sure that people can only edit their own account. In a before action you will want to add.
redirect_to root_path unless current_user == user_you_are_editing
What I would do:
Create a Model called UserPreferences that belongs_to :user, give this Model the attributes 'background_color', etc...
Add statement to user has_one :user_preferences
Create a form for the prefs like any Rails Model, that can only be accessed by current_user.
Use current_user.user_preferences to refer to these values, you can enhance this by placing alias methods in User, for example:
class User < ActiveRecord::Base
def background_color
self.user_preferences.background_color
end
end

getting session user_id in a model

I have "updated_by" field in most of my models. I need to update this field with the current user id.
What is the best way to obtain session user is in a Model?
Where can I put logic to populate the "updated_by" field for any models which respond_to that method?
Thanks
I suggest you to store the current_user in the ApplicationController. You can handle there any logic you want (read the cookie, redirect to the home page if the user have not cookie etc). So storing the current_user variable in the ApplicationController let you access to that from every model or controller you want. Check this link http://niczsoft.com/2010/03/rails-current-user/

Resources