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
%>
Related
I am working on active_admin in rails in which I want to add an action which will run a service.
action should appear in the index view. so, how can i add a action which runs this service.
My code of app/admin/website.rb is
ActiveAdmin.register Website do
actions :index
index do
selectable_column
id_column
column :state
column :name
column :created_at
column :updated_at
end
end
in above file i want to check that id state='draft' then it should run the action which runs a service.
My service file app/services/website_verify_state_service.rb:
class WebsiteVerifyStateService
def self.process!(website)
new(website).process
end
def initialize(website)
#website = website
end
def process
site_response = self.class.post("#{BASE_MONO_URL}reseller/account/site",
site_data = JSON.parse(site_response.body)['data']
if site_data
#website.update(published: true) if site_data[0]['site']['lastPublishDate'].present?
end
end
end
SO my only concern is that how i call this service through action when from active admin.
Thanks in advance
You can add conditional actions to the index table:
ActiveAdmin.register Website do
actions :index
index do
selectable_column
id_column
column :state
column :name
column :created_at
column :updated_at
actions do |website|
item('Verify state', verify_admin_websites_path(website.id), class: 'member_link') if website.state == 'draft'
end
end
member_action :verify do
# do your magic here, like or whatever you do
WebsiteVerifyStateService.process!
redirect_back(fallback_location: root_path)
end
end
I know it is simple but I can't get my head around a solution.
It is a job board site. Lets say it's functionality similar to this site. When a user fill all required information and click "To next step" or "Preview", another page loads with all filled data. That page is similar to the final page when data is saved.
When user on preview page, it can go forward and submit the page (in this case it will be saved to DB). Or, click back to Edit the job.
I tried the following::
Within _form.html.erb I added a preview button
<%= f.submit "Preview", :name => 'preview' %>
Within JobControllers I altered create method
def create
if params[:preview]
#job = Job.new(jobs_params)
render 'jobs/preview'
else
#job.save
end
end
Created a Preview view /jobs/preview.html.erb
Now I have 2 problems.
1- Within my preview page, I have an edit button like so: <%= link_to "Edit Job", edit_job_path(#job) %>. But I have an error because I can't find #job. Error says: No route matches {:action=>"edit", :controller=>"jobs", :id=>nil} missing required keys: [:id]
SOLUTION Changed like to <%= link_to 'Back to edit', 'javascript:history.go(-1);' %>
2- How I would submit and add to my DB all information on preview page?
Thank you.
Once I've given a similar task. What I've done is to save records, but not to publish. In my index (resource listing) action of relevant controller, I only fetch published records. Also show action prechecks if that record's published attribute is set to true.
What was my model/controllers looked like before
#model
class Book < ActiveRecord::Base
...
scope :active, -> { where(published: true).some_other_queries }
self.active?
(published && some_other_requirements)
end
...
end
#controller
def index
#books = Book.active
...
end
def show
if #book.active?
render 'show'
...
else
...
end
end
First added a secret key for previews.
#model
def secret
#some custom random key generation
# e.g. Digest::MD5.hexdigest("#{id}_#{ENV['RAILS_SECRET']}")
end
Then added preview action to controller
def preview
# i don't check if the record is active.
# also added a security layer, to prevent irrelevant guys to view
# that record
if #book.secret == params[:secret]
render 'show'
else
...
end
end
In dashboard
...
= link_to "Preview", preview_book_path(book, secret: book.secret)
...
then added a member route
#routes
resources :books do
get :preview, on: :member
end
When I have to do something like this what I normally do is create a review table in my app. This table looks just like the table that is going to saving to.
When they press the "Approved" or "Save" button just populate the new table with the proper data.
I like to create a routes to handle this
resources :something do
match 'move_to_something_else' => 'somethings#move_to_something_else', as: :move_to_something_else, via: :all
end
Now on the controller we can do the following:
def move_to_something_else
#something = Something.find(params[:id])
#something_else = SomethingElse.new
#something_else.name = #something.name
....
#something_else.save
redirect_to something_else_path(#something_else)
end
Alternative you could add a state to your table with the default value of 'draft'
# config/routes.rb
resources :something do
match 'published' => 'somethings#published', as: :published, via: :all
end
# Controller
def published
#something = Something.find(params[:id])
#something.state = 'published'
#something.save
redirect_to something_path(#something)
end
Activeadmin layout is not just a file, its a collection of components.
How can I override some of the components like, logo, navigation with activeadmin.
The activeadmin layout components are very easy to customize. What you need to do: Just define a module that opens ActiveAdmin::View.
you can have a custom_activeadmin_components.rb in initializers or admin directory where you defined all of your activeadmin resources. I prefer to put it in the directory where your activeadmin resources are. Then override any module you want:
here is a sample:
module ActiveAdmin
module Views
class Header < Component
def build(namespace, menu)
super(:id => "header")
#namespace = namespace
#menu = menu
#utility_menu = #namespace.fetch_menu(:utility_navigation)
build_site_title
build_global_navigation
build_utility_navigation
#you can add any other component here in header section
end
def build_site_title
render "admin/parts/logo"
end
def build_global_navigation
render "admin/parts/main_nav"
end
def build_utility_navigation
render 'admin/parts/language_options'
insert_tag view_factory.global_navigation, #utility_menu, :id => "utility_nav", :class => 'header-item tabs'
render 'admin/parts/branch_in_header'
end
end
module Pages
class Base
def build_page_content
build_flash_messages
div :id => :wizard_progress_bar do
render 'admin/parts/wizard_progress_bar'
end
div :id => "active_admin_content", :class => (skip_sidebar? ? "without_sidebar" : "with_sidebar") do
build_main_content_wrapper
build_sidebar unless skip_sidebar?
end
end
end
end
end
end
You can customise active admin page in admin/your_model.rb file.
Sample code for active admin is as follows.
ActiveAdmin.register User do
menu :label => "Our User", :priority => 3 #rename menu & set priority#
#for index page#
index :title => 'Our User' do #set page title#
# index :download_links => false do
selectable_column
column :title
column :category do |e| #want to change name of category
e.categoryone
end
column :address
default_actions#this will add default action i.e. show|edit|delete#
end
#end index#
#for controller#
controller do
actions :all, :except => [:edit, :new] # you can decide which all methods to be shown in show page.
end
#end controller#
#show start page#
show do |user|
h3 "User Details"
attributes_table do
row :title
row :description
row :address, :label=>"User Address" #overide address label
row :country
row :approval
end
h3 "Activity Photoes"
attributes_table do
user.uploads.each do |img| #call associated model. Here i want to display uploaded image of upload.rb file
row(" ") do
link_to image_tag(img.to_jq_upload['small_url']), admin_upload_path(img)#here i have added upload module to admin thats y i can directly give path to the upload record of admin module#
end
end
end
active_admin_comments # to show comment block of active admin
end
#show end#
#filer(search) start righthand side panel#
filter :title
filter :category
filter :address
#end filter#
#for menu on show page#
action_item only:[:show] do # this add "Approve User" button on the right hand side of show menu only as we have specified only show method
if User.find(params[:id]).approval == true
link_to "Approve User", approv_user_path(:id => params[:id])#call custom method of normal rails controller#
end
end
#end menu#
#start add side bar on page#
sidebar "Project Details" do
ul do
li link_to("Profile", new_project_path)
end
end
#end side bar#
end
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
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