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/
Related
I have two models: User and Dream. User has_many :dreams and Dream belongs_to :user. I have two controllers for users and dreams as well. I want to create new Dream with form_for with a reference to a particular User. But it shouldn't be specified by me, it should somehow (and this is where I'm stuck) track on which User's page I pressed "Create new dream", and create it for this User.
I managed to do this with using only Users Controller (for managing Dreams as well), with passing user_id parameter in URL, and with hidden field. But I realize this is not a great way to do it, because anybody can edit URL or hidden field's value and create new Dream for any User.
I'm looking for a way to make two controllers communicate with each other under the hood. Or maybe this is not what I need and I miss some conceptual nuance of MVC or whatever. I need someone to push me in the right direction.
If you have login functionality, then you can define a method in ApplicationController that returns the user that matches the session token provided by the request, and then do current_user.dreams.create(params) which will create the dream with reference to whichever user is returned by current_user and never put any information about the user into the client's view.
If you don't have login functionality, then I wouldn't worry about the fact that it can be edited, since at that point anyone would be able to create a dream for any other user anyway just by visiting that page.
edit: e.g. I've often used something like this:
def current_user
#current_user ||= User.find_by(session_token: session[:session_token])
end
You can add an optional user_id param to the new action in the DreamsController. It that param build the new dream on that User.
def new
user_id = params[:user_id]
#dream = if params[:id].present?
User.find(params[:id]).dreams.build
else
Dream.new
end
end
Then your link will be something like
<%= link_to "Create New Dream", {:controller => "dream", :action => "new", user_id: user[:id]}%>
I think that is the way things are done of such kind.
For:
anybody can edit URL or hidden field's value and create new Dream for any User
If you have single user through out the app, he can do anything ; he is superAdmin
If multiple users
they must have different roles like; moderator, superadmin, admin
in such case; authentication alone cannot do all the things you have to use some method of authorizationmechanism like cancan, cancancan, pundit,etc.
these basically prevents any user to do something nasty they are unauthorized.
If any user modifies the hidden field value, you have to check if he is authorized to do so or not.
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
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
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
So I have a Rails app with a Post model. One of the fields is collection_id.
Each post should have the ID of the latest collection at the time of posting. If I have that ID in the backend, and I remove the form field for collection_id, how can I make sure this ID goes into the database without having a hidden_field in the Rails frontend?
The problem with a hidden field is that users could use a web inspector to change the value. This needs to be secure.
What's the best way to do this?
If you have that ID in your backend, you can pass it in your controllers action before saving:
#post = Post.create(params[:post])
#post.controller_id = variable_holding_the_id
if #post.save ...
or in some cases you can do it in the model with a callback:
after_create :set_collection_id
def set_collection_id
self.collection_id = variable_holding_the_id
end