Active Admin Permitted Params - ruby-on-rails-4

Is there a way to tell whether I am in create or edit mode from inside the permit_params block of active admin? I'd like to merge created_by and updated_by when I'd creating a new record. When I'm editing an existing record I only want to merge updated_by.
Here's my code:
ActiveAdmin.register Group do
menu parent: "Groups", priority: 0
permit_params do
permitted = [:name, :description, :group_type_id, :owner_user_id]
permitted.merge!(updated_by: current_admin_user)
permitted
end
I'd like to say something like:
permitted.merge!(created_by: current_admin_user) if new_record?
new_record? is an active admin method but it only seems to work in forms.
Any ideas?

You can merge it in the create and update action, too:
controller do
def create
params[:group].merge!(created_by: current_admin_user)
create!
end
def update
params[:group].merge!(updated_by: current_admin_user)
update!
end
end

Related

Overriding a child association's setter from the parent model

I have a parent User model, and each user has_one Contact which hold's the user's contact info.
One of the contact fields is the email. For various legacy reasons and reasons outside the context of this question, I'd love to be able to call #email directly as if it were a property of User
In other words I'd like to do this -
user.email
user.email = "foo#example.com"
Instead of this -
user.contact.email
user.contact.email = "foo#example.com"
I laid out my models as follows, overriding the child's getter/setter from the parent User -
class User < ActiveRecord::Base
has_one :contact
def email
contact.email
end
def email=(value)
contact.email = value
end
end
class Contact < ActiveRecord::Base
belongs_to :user
end
You may have already noticed the problem with the setter - when the User is saved, it doesn't save the child model.
What's the most robust to work around this?
Thanks!
Ok, found the solution for anyone curious - auto-saving
ActiveRecord::AutosaveAssociation is a module that helps with exactly this - saving child associations properly when the parent is saved.
Just need to include an autosave: true. Example -
has_one :contact, autosave: true
It also takes care of destroying records marked for deletion, and a few other fancy things.
I also did a quick check, and it smartly doesn't hit the DB unless it really needs to. That is, if you update the parent only it doesn't bother saving the child association with an other SQL UPDATE statement.
Check out the documentation here.

Is there a better way of overriding devise controller in rails

I have to populate a field in my db when a new user signs-up.But this field is not to be filled by the user, instead will be populated by the application in the db. Here is what i tried:
Added the extra field(investorId) in the migration file.
Overridden the devise controller:
def create
super
if #user.save
#user.investorId = #user.id + X---> some number
#user.save
end
end
Though it is working fine, but I want to know if there are better ways of doing it since I am doing it for the first time.
Thanks,
Sachin
If you need to generate a value before you create a record, you can use the before_create or after_create callbacks on the model.
User < ActiveRecord::Base
after_create :generate_investor_id
private
def generate_investor_id
reload
investor_id = "#{self.id}something"
update_attribute(:investor_id, investor_id)
end
end
Don't override your devise controller, there is no benefit of doing this. Simply put the below logic in your after_create callback -
User < ActiveRecord::Base
after_create :create_investor_id
private
def create_investor_id
self.update_column(:investor_id, id+some_number)
end
end

ActiveAdmin specify filter form url

I am using active-admin(AA, 1.0.0) in a rails 4.2 app. I am displaying a list of online users. I have to display a list of users with scopes for each type of user and filters as per the User model fields. Also, I need to display a list of online users on another page.
User(dropdown)
=> Accounts
=> Online Users
To display the users list, i have
ActiveAdmin.register User, as: 'User' do
menu :parent => "Users", :label => "Accounts"
...
end
To display the online users list, i have
ActiveAdmin.register User, as: 'Online User' do
menu parent: "Users", label: "Online Users", url: '/admin/online_users'
actions :index
filter :id
filter :name
filter :email
...
end
Now,the filters are getting displayed properly on the "Online Users" page, but when the filter form is submitted, its submitted to "/admin/users" rather than to "/admin/online_users". Can I pass the url to the filter form? If not, what is the right solution to this problem.
Thanks.
You can redefine the collection_path method which is used by the filter form builder like this:
controller do
def collection_path
admin_online_users_path
end
end

How make Current user as admin by using update query in Rails 4

I need to do current user as admin. So I am trying to update my users table. In my user table there is a field called admin which has boolean datatype.
if current_user.admin != true
current_user.update_attributes(:admin => 'true')
end
But this is not reflecting in my table. So what should I do here?
Try this
if current_user.admin != true
current_user.admin = true #if admin is boolean
current_user.save
end
This should work.
make it more "generic"
class User
def grant_admin!
update_attribute(:admin, true)
# you dont need to check if he is alread an admin since rails won't
# write to DB unless any value changed
end
end
# in controller
#...
current_user.grant_admin!
Do yourself a favor and have a look at https://github.com/ryanb/cancan and its railscasts

Updating Roles in rolify using ActiveAdmin

Using Rails 4.0, ActiveAdmin, Rolify and CanCan, Adding and removing user roles via the activeadmin panel does not save (commit to database).
The my ActiveAdmin User and User Model look okay as I can list all the roles that apply to a user using check_boxes. Although when adding any roles or removing any roles via the checkboxes the changes do not get applied.
I get a notification that the user was updated successfully but as I look through the database or render the page, the roles have not been updated.
How can I get the roles to update when the form is saved?
Edit:
Using Devise also.
The solution here is to allow the ActiveAdmin controller to update the role ids related to the user.
ActiveAdmin.register User do
permit_params :email, :password, :password_confirmation, role_ids: []
Here's a form that shows a check box for each global role.
form do |f|
f.inputs "User Details" do
f.input :email
f.input :password
f.input :password_confirmation
f.input :roles, as: :check_boxes
end
f.actions
end
While we're at it, we might as well make it possible to update the user without entering their password:
# Allow form to be submitted without a password
controller do
def update
if params[:user][:password].blank?
params[:user].delete "password"
params[:user].delete "password_confirmation"
end
super
end
end
Put all of this in the app/admin/user.rb.
I just ran into this issue. The problem was with validation of presence (which I think is occurring in the database ":null => :false"). In order for the update to save, I had to fill out all fields (including password/password confirmation).
I had to add some controller code to make this work, I hope this helps:
Remember to permit the attributes you're accepting in active_admin as such (this will create the permitted_params method I'll be referring to in a bit.
Note that since we're not saving role_ids directly to the user, it doesn't even have to be a permitted param.
permit_params :email, :password, :etc
Create a private method we could call from the create and update controllers. This method will just iterate over non-empty ids, find the associated roles, and add them to user.roles.
The create and update methods simply find call the add_roles method prior to continuing execution. ActiveAdmin makes the the existing user available through resource, but not through create. We have to find it ourselves in create!
controller do
def create
#user = User.new(permitted_params[:user])
add_roles(#user)
create!
end
def update
add_roles(resource)
update!
end
private
def add_roles(resource)
resource.roles = []
params[:user][:role_ids].each { |r| resource.roles.push(Role.find(r)) unless r.blank? }
end
end
In the activeadmin form, you can add:
form do |f|
# other inputs
f.input :roles, as: :select, multiple: true, collection: Role.all
end
And in the show page, you can display the roles as such:
show do
attributes_table do
# other rows
row :roles do |r|
r.roles.map { |role| role.name }.join(", ")
end
end
Hope this helps!