RailsAdmin - pass parameters to scopes - ruby-on-rails

I defined several scopes on my model and use them in rails_admin.
scope :foo , ->() { where(status: 'active')}
...
list do
scopes [nil, 'foo']
I want to create scopes where I can pass parameters and then load those from rails_admin. Something like this:
scope :bar , ->(query) { where(status: query)}
But because RA does not pass parameter I keep getting
wrong number of arguments (0 for 1)
Does anyone have any suggestions? I am using Rails 4.1.14 with rails_admin 0.8.1 and mongoid 5.0

I solved this via creating custom action and then specify it to use index template. It shows up next to List, Add New and other actions instead of below filters.
class Article
include Mongoid::Document
field :title, type: String
...
belongs_to :user, counter_cache: true
scope :by_user, ->(user) { where(user: user) }
...
end
# in rails_admin.rb
class Myarticles < RailsAdmin::Config::Actions::Base
RailsAdmin::Config::Actions.register(self)
register_instance_option :collection do
true
end
register_instance_option :only do
Article
end
register_instance_option :controller do
proc do
#objects = Article.by_user(current_user)
render :index
end
end
end
Related question Rails_admin custom action specify template name

Another way is using cancan. You can do this in the ability file:
def initialize(user)
can [:read], Profile, user_id: user.id
end

Related

How to display scopes based on the role of the user in active admin?

I am getting an error:
undefined local variable or method `current_admin_user' for #<ActiveAdmin::ResourceDSL
How can I access current_admin_user object here?
ActiveAdmin.register Job do
def quick_filters
if current_admin_user.super_admin?
[:all, :draft, :scheduling, :rejected]
else
[:all, :scheduling, :rejected]
end
end
quick_filters.each do |a|
scope a
end
end
This is working:
controller do
def scoped_collection
#jobs = if current_admin_user.super_admin?
super.includes :trip, :car, :concierge, :creator, :job_template
else
super.where(concierge_id: current_admin_user.id).includes :trip, :car, :concierge, :creator, :job_template
end
end
end
I think this should work:
ActiveAdmin.register Job do
scope :all
scope :draft, :if => proc { current_admin_user.super_admin? }
scope :scheduling
scope :rejected
end
The DSL for setting up scopes is evaluated at server startup time and does not have access to request cycle based data (like the logged in user). To get around this ActiveAdmin has the concept of wrapping code code with proc so that the enclosed code evaluation is deferred to request-cycle-time.
Good luck!

Skip default scope when you filtering in ActiveAdmin

I have a default scope in ActiveAdmin excluding 'pending' status because we have a lot of this status and we didn't want to see it by default. But when we search by filter, we want to skip this default scope and include 'pending' status. How to do this ?
My model :
class MyModel < ActiveRecord::Base
validates :status, presence: true,
inclusion: { in: %w(pending published accepted declined cancelled) }
scope :published, lambda {
where("bookings.published_at IS NOT NULL")
}
end
ActiveAdmin Model :
ActiveAdmin.register MyModel do
actions :index, :show
config.sort_order = "locked_at_desc"
config.scope :published, default: true
index do
column :id
column :status
actions
end
end
You need to add :all scope in the admin file. Then you can search by filter which will include pending status under the :all scope. If you need to speedup loading all your records, you may provide show_count: false in :all scope.
ActiveAdmin.register MyModel do
...
scope :published, default: true
scope :all # scope :all, show_count: false
...
end

How to include sub-object in json response

Hi I am trying to include the roles of a user when rendering json doing User.all
I am using ruby on rails and Mongoid
I only get the role_id in my response...
role_id":"56cb596bc226cb5c04efd1cb
User model:
class User
include Mongoid::Document
include ActiveModel::SecurePassword
has_many :role
belongs_to :store
has_many :orders
Role model:
class Role
include Mongoid::Document
belongs_to :user
field :name, type: String
field :active, type: Mongoid::Boolean
the response I get:
{"_id":"...","api_key":"...","email":"jesus#drinkz.io","name":"... Garcia","password_digest":"...","promotion_ids":[],
"role_id":"56cb596bc226cb5c04efd1cb"}
How I get the response: GET /api/v1/users
def index
#user = User.first
respond_with #user
end
How can I embed roles in the response ?
You'll get the JSON that represents User alone if you don't include the Role as well. You can do something like below
def index
#user = User.first
respond_with(#user, :include => :role)
end
Old school way would be,
def index
#user = User.first
respond_to do |format|
format.json { render :json => #user.to_json(:include => :role) }
end
end
Add gem 'active_model_serializers' to your gemfile if you are not already using it . Then generate an user serializer using
rails generate serializer user
Then add following to app/serializers/user_serializer.rb file.
class UserSerializer < ActiveModel::Serializer
attributes :id, :email,:name, :password_digest, :promotion_ids, :api_key
has_many :roles
end

Retrieve created object from InheritedResources#create

In my Rails app, I have the following objects:
Group: has_many users through group_membership
GroupMembership: belongs_to user, belongs_to group
User: has_many groups through group_membership
Users can create groups. When this happens, I want to automatically add the user to the group. In my GroupsController, I have the following (extending InheritedResources):
super do |success, failure|
if success
GroupMembership.create(:user_id => current_user, :group_id => ???)
...
end
The problem is I cannot retrieve the object that super created. Is there a way to do this? Or better, is there a way to change the LockGroup model so that it always performs this association?
When the callback is fired, the controller already has the standard instance variable corresponding to the created group: #group !!
class GroupController < InheritedResources::Base
def create
super do |success, failure|
if success
GroupMembership.create(:user_id => current_user, :group_id => #group.id)
...
end
end
end
I assume the params key given for your group is :group. Then you can used the nested_attributes_for option in the model. Then you can set those in a before filter from the create action:
class User < ActiveRecord::Base
accept_nested_attributes_for :group_membership
end
# on your controller
before_filter :add_user, :on => [:create]
def add_user
params[:group][:group_membership_attributes] = {}
params[:group][:group_membership_attributes][:user] = current_user
end
or you build the group membership on user initialize:
class User < ActiveRecord::Base
def after_initialize
build_group_membership
end
end
# on your controller
before_filter :add_user, :on => [:create]
def add_user
params[:group][:user] = current_user
end
and it should automagically work.

Keeping named_scope Extensions DRY

In Rails, you can add a block after a named_scope for additional, context-sensitive methods like so:
class User < ActiveRecord::Base
named_scope :inactive, :conditions => {:active => false} do
def activate
each { |i| i.update_attribute(:active, true) }
end
end
end
In this example, the activate method is being defined not on the User class, but on the ActiveRecord::NamedScope::Scope object.
I have a series of three scopes that need to have identical method definitions. In the interests of not repeating code, how would I abstract that block such that I could define it once and pass it to each named_scope?
Firstly, great question--I didn't know about that feature of named scopes! The following works for me:
class User < ActiveRecord::Base
add_activate = lambda do
define_method "activate" do
each { |i| i.update_attribute(:active, true) }
end
end
named_scope :inactive, :conditions => {:active => false}, &add_activate
end
You can pass the add_activate block as the last argument to any named scopes that need the activate method.
Much better:
http://tuxicity.se/rails/dry/2009/01/04/share-named-scopes-in-rails.html
module NamedScope
def self.included(base)
base.class_eval do
named_scope :inactive, :conditions => {:active => false} do
def activate
each { |i| i.update_attribute(:active, true) }
end
end
end
end
end
Save in your /lib directory (put a require in an initializers in rails 3) and include NamedScope in your User class

Resources