Currently I have User model, which is registered in user.rb as a new resource for ActiveAdmin. Generated page displays all users with scopes (all/journalists/startup_employees). Now I want to create another page for the same resource, and the same scopes, but there should be only records with waiting field set to true (and the previous page should displays only this with :waiting => false). How could I do that? I know I could do that with filters, but I need two separate pages, with two links in menu.
// SOLUTION
It was even easier than advices (thanks guys!):
ActiveAdmin.register User, :as => 'Waitlist User' do
menu :label => "Waitlist"
controller do
def scoped_collection
User.where(:waitlist => true)
end
end
# code
scope :all
scope :journalists
scope :startup_employees
end
ActiveAdmin.register User do
controller do
def scoped_collection
User.where(:waitlist => false)
end
end
# code
scope :all
scope :journalists
scope :startup_employees
end
STI (Single table inheritance) can be used to create multiple "sub-resources" of the same table/parent model in Active admin
Add a "type" column in user table as a string
Add this to User model to mirror waiting field with type field
after_commit {|i| update_attribute(:type, waiting ? "UserWaiting" : "UserNotWaiting" )}
Create the new models UserWaiting and UserNotWaiting
class UserWaiting < User
end
class UserNotWaiting < User
end
Create Active Admin resources
ActiveAdmin.register UserWaiting do
# ....
end
ActiveAdmin.register UserNotWaiting do
# ....
end
You can run a first-time sync in console
User.all.each {|user| user.save}
..............
Another way could be to skip the type column (steps 1,2 and 5) and solve the rest with scopes.
Step 3 and 4 above
Then create the scopes
#model/user.rb
scope :waiting, where(:waiting => true)
scope :not_waiting, where(:waiting => false)
Scopes in Active Admin
#admin/user.rb
scope :waiting, :default => true
#admin/user_not_waitings.rb
scope :not_waiting, :default => true
Just make sure the other scopes in these two pages are also filtered on waiting/not_waiting
you could use a parameter to distinguish the cases and render different actions depending on the parameter:
link_to users_path(:kind => 'waiting')
and in the users_controller.rb
def index
if params[:kind]=='waiting'
#users= Users.where(:waiting => true)
render :action => 'waiting' and return
else
# do your other stuff
end
end
then put your new, different page (partial) in app/views/users/waiting.html.erb
If you want to use a different layout for this page add the layout parameter to render:
render :action => 'waiting', :layout => 'other_layout' and return
Related
I have a has_many & belongs_to associations between company and worker. I want to be able to add a worker to a company via a link in my workers index page. I want that to save the worker record belonging to the logged in company and update the company/workers index page with the new worker added to their workers.
I have been unable to do this. Here is what is happening:
My routes have something like:
namespace :company do
resources :workers, :only => [:index, :create]
end
resources :workers
I have a before_action method that has the cookie session with the company access token in my controllers:
ApplicationController:
#company = Company.find_by_access_token("vZAni6K6")
cookies[:access_token] = #company.access_token
And Company::WorkersController
render :file => "public/401.html", :layout => nil, :status => :unauthorized and return if cookies[:access_token] != #company.access_token
In my workers/index.html.haml path I have:
= "There are #{#workers.count} workers!"
They are:
- #workers.each do |worker|
= worker.name
= link_to "Hire a worker", company_workers_path(:worker_id => worker), :method => :post
%%br
%p= #company.name
I want the to be able to click the "Hire a worker link" and then be redirected to the company/workers.html.haml path that then will list their workers updated with the recent addition of the worker just added via the link.
When I currently click the link(say for worker #2 in by database) instead of taking me to company/workers path it takes me to
company/workers?worker_id=2
And it doesn't save the worker to the association with the company.
My company/workers controller has the following:
def create
#worker = #company.worker.build(:worker_id => params[:worker_id])
#worker.save
redirect_to :action => 'index'
end
Remember I have a before_action on my controllers that saves the #company instance variable before calling other controller methods as well.
I have a model Worker that belongs_to a company & a model Company that has_many workers and I have added the reference key in my migration already.
What is the problem? Why the weird route and why are my records not saving, I am a bit of a newb so forgive the simple question.
At first look, I see you may have two errors:
your Company model class has_many workers, so to assign (or add) a worker to a company I believe it must be something like:
#worker = Worker.find(params[:worker_id])
#worker.company = #company
#worker.save!
# depending in your schema, it could be something like this as well:
# #company.workers << #worker
to redirect to company/workers, as you use nested routes, it must be like
redirect_to company_workers_path(#company)
Hope this helps!
I have created a custom page with ActiveAdmin as follows:
ActiveAdmin.register_page "message_list" do
controller do
def index
#collection = client().account.messages.list.sort_by{ |message| Date.rfc2822(message.date_sent) }.reverse
render :layout => 'active_admin'
end
end
end
I have created an index.html.erb file with a table that I want to display on this page. This however is not optimal. How do I use the active admin standard table layout that also comes with pagination and display it with my table info? I know that ActiveAdmin PageDSL Class does not include #index and therefore I can't simply do:
index do
selectable_column
id_column
column :to
column :from
default_actions
end
In addition to achieving the ActiveAdmin table layout on a custom page, how do I change the Title of the page itself? As of now it is called "Index".
An easier method would be to define an ActiveAdmin resource for your message class, Message, and limit the actions to only allow :index.
ActiveAdmin.register Message do
actions :index
index do
selectable_column
id_column
column :to
column :from
default_actions
end
controller do
def scoped_collection
super.where(account_id: account.id).order(:date_sent)
# Or provide a custom collection similar to the current implementation:
# client().account.messages.list.sort_by{ |message| Date.rfc2822(message.date_sent) }.reverse
end
end
end
It is also possible to rename the resource if necessary by providing an :as option to the #register method:
ActiveAdmin.register Message, as: "Account Message" do
# ...
end
While the accepted answer works well if you can use an ActiveAdmin resource instead of a custom page, it is possible to get an index-style table on a custom page via Arbre:
<%=
Arbre::Context.new({}, self) do
table_for(client().account.messages, sortable: true, class: 'index_table') do
column :id
column :created_at
end
end
%>
I have some 10,000+ records in my model. In active_admin index page for that model I have set config.paginate = false. So all the 10,000+ records are shown by default.
How can I limit the number to say last 500 records. I have tried using the below method described here, but its not doing anything to the index page.
ActiveAdmin.register Post do
controller do
def scoped_collection
Post.all.limit(500)
end
end
end
set custom # of rows on page with controller before_filter
controller do
before_filter :set_per_page_var, :only => [:index]
def set_per_page_var
session[:per_page]=params[:per_page]||30
#per_page = session[:per_page]
end
end
and render sidebar with corresponding text input (you can render it as a drop-list)
#...
sidebar('Rows on page', :only => :index) do
form do |f|
f.text_field nil, 'per_page', :value => session[:per_page]
end
end
The issue is this code in Active Admin:
module ActiveAdmin
class ResourceController < BaseController
module DataAccess
def per_page
return max_csv_records if request.format == 'text/csv'
return max_per_page if active_admin_config.paginate == false
#per_page || active_admin_config.per_page
end
def max_csv_records
10_000
end
def max_per_page
10_000
end
end
end
end
When the paginate config option is set to false, it defaults to the number value returned by max_per_page. If you're fine with overriding it globally, you can put this in an initializer:
# config/initializers/active_admin_data_access.rb
module ActiveAdmin
class ResourceController < BaseController
module DataAccess
def max_per_page
500 # was 10,000
end
end
end
end
I was looking for an answer to this same question. I was unable to limit the number of records, so instead I have opted for putting a default value in one of my filters that guarantees an empty page when it loads.
(NOTE: I stole this idea from this stackoverflow question here:: Set ActiveAdmin filter default value )
Example::
In this example, I set a filter called "my_filter_id" equal to "0" in the "before_filter" method if all of the parameters are blank.
ActiveAdmin.register MyModel do
before_filter my_filter_id: :index do
params[:q] = {my_filter_id_eq: 0} if params[:commit].blank?
end
end
Use
Post.limit(500) instead of Post.all.limit(500) so it will minimize the latency.
controller do
def scoped_collection
Post.limit(500)
end
end
index :pagination_total => false do
selectable_column
column :id
column :user_name
column :country
column :city
end
Hope this will help someone.
Try below code. Replace something with your model name.
result = Something.find(:all, :order => "id desc", :limit => 5)
while !result.empty?
puts result.pop
end
In my Rails 4 app I am starting to move my logic to the model (working on the Fat Model principle). However, I'm a little unsure on how best to tackle the basics.
My app displays bookings for the logged in user. In my BookingsController I have an action that displays the confirmed bookings:
def confirmed
#bookings = Booking.where(:status => 3, :accommodation_id => current_user.accommodation.id).order('updated_at DESC')
end
However, I have tried to move the logic to the controller so that the BookingsController now looks like this:
def confirmed
#bookings = Booking.confirmed_bookings
end
and the Booking model looks like this:
def confirmed_bookings
bookings = where(:status => 3, :accommodation_id => current_user.accommodation.id).order('updated_at DESC')
end
I am receiving an undefined method `confirmed_bookings' error and not sure what I'm doing wrong. A fix for this and some simple "starter" advice would be much appreciated.
Split your scopes in reusable chunks:
scope :confirmed, ->{ where(:status => 3) }
scope :for_user, ->(user) { where(:accommodation_id => user.accommodation.id) }
def self.confirmed_bookings_for(user)
confirmed.for_user(user).order('updated_at DESC')
end
Notice, it' would be much better not to refer to the user at all, since it's for an accommodation.
This should work if you change the confirmed_bookings method to
self.confirmed_bookings
...
end
[EDIT] Missed the part about the current user, that function will be unavailable in the model, one solution is to pass it as a parameter to the confirmed bookings function:
class Booking < ActiveRecord::Base
def self.confirmed_bookings_for (user)
where(:status => 3, :accomodation_id => user.accomodation.id).order('updated_at DESC')
end
...
end
Then in your controller you can write
#bookings = Booking.confirmed_bookings_for current_user
I have an active admin resource like this:
ActiveAdmin.register Snippet do
menu label: "Text Snippets"
config.clear_sidebar_sections!
index download_links: false do
column :key if current_admin_user.developer?
column :description
column :contents
default_actions
end
form do |f|
f.inputs do
f.input :description
f.input :contents
end
f.buttons
end
end
Notice in the index block, I'm only adding the key column if the current admin user is a developer. I want to apply this kind of filtering to the available actions.
I tried added this at the top of the resource definition:
actions current_admin_user.developer ? :all : :index, :edit
But I get a NameError on current_admin_user. For some reason, outside of the configuration blocks, the active admin current_admin_user helper doesn't exist.
So, how could I go about filtering actions based on the current user's priviliges?
you have to use a proc... current_admin_user works only when the app it's running, not when you declare your class..
example..
action_item :only => [:edit], :if => proc { current_admin_user.developer? } do
#enter code here
end
You can also use CanCan for this.. and place controller.authorize_resource at the beginning. Check the activeadmin documentation for this.
Another way to do it is overriding the action_methods in the ActiveAdmin controller.. like this
actions :all
controller do
def action_methods
if current_admin_user.developer?
super
else
super - ['show', 'destroy', 'new', 'create']
end
end
end
this works cool if you have multiple roles.
btw you should use developer? instead of developer (off course if the developer method returns a boolean as I suspect)
UPDATE
in version 0.6+ you should stick with CanCan, for more information check the activeadmin documentation http://www.activeadmin.info/docs/13-authorization-adapter.html#using_the_cancan_adapter