Custom CSV Export in Active Admin Index Page Problems - ruby-on-rails

A developer built this app and I'm not well-versed in Ruby at all. So please bear with me. In the Active Admin files, we have several admin pages/tables: artworks, artists, transaction, investors, etc.
In the artworks.rb admin page, I have added the custom CSV export to the bottom:
# frozen_string_literal: true
# rubocop:disable Metrics/BlockLength
ActiveAdmin.register Artwork do
filter :title
filter :auction_id, collection: proc {
Auction.where.not(url: [nil, '']).order(:url).pluck(:url, :id)
}, as: :searchable_select
filter :artist_id, collection: proc { Artist.order(:name).pluck(:name, :id) }, as: :searchable_select
controller do
def scoped_collection
super.includes(:auction, :buyer, :underbidders, :artist)
end
end
index do
column :lot do |artwork|
link_to(artwork.lot, admin_artwork_path(artwork)) if artwork.lot
end
column :auction
column :title
column :artist
column :image_url
column 'Auction date' do |artwork|
artwork.auction&.start_date
end
column('Buyer', &:buyer)
column('Underbidders', &:underbidders)
column :status
actions
end
show do
attributes_table do
row :lot
row :auction
row :title
row :artist
row :image_url
row 'Auction date' do |artwork|
artwork.auction&.start_date
end
row('Buyer', &:buyer)
row('Underbidders', &:underbidders)
row 'Transactions' do |artwork|
artwork.transactions.map do |transaction|
link_to(
"#{transaction.investor&.name} --- #{price_with_currency(transaction)}",
admin_transaction_path(transaction)
)
end
end
row :status
active_admin_comments
end
end
controller do
def create
create! do |success, _|
success.html { redirect_to collection_path }
end
end
end
permit_params :lot, :title, :artist_id, :url, :status, :auction_id, :image_url,
transactions_attributes: %i[
id
artwork_id
investor_id
auction_id
category
price
currency
]
form(html: {multipart: true}) do |f|
f.inputs do
f.semantic_errors
f.input :lot
f.input :title
f.input :artist, as: :searchable_select, include_blank: true
f.input :image_url
f.input :status, as: :select, collection: Artwork.statuses.keys, include_blank: false
f.input :auction, as: :searchable_select, include_blank: true, collection: Auction.order(:url).pluck(:url, :id)
f.inputs 'Transactions' do
f.has_many :transactions, heading: false do |ff|
ff.input :investor, as: :searchable_select
ff.input :auction_id, input_html: {value: f.object.auction_id}, as: :hidden
ff.input :category, as: :select, collection: Transaction.categories.keys, include_blank: false
ff.input :price
ff.input :currency, as: :select, collection: Transaction.currencies.keys, include_blank: false
end
end
end
f.actions
end
csv do
column :title
column :lot
column 'Auction' do |artwork|
artwork.auction&.url
end
column 'Artist' do |artwork|
artwork.artist&.name
end
column :image_url
column 'Auction date' do |artwork|
artwork.auction&.start_date
end
column 'Buyer' do |artwork|
artwork.buyer&.name
end
column 'Underbidders' do |artwork|
artwork.underbidders&.name
end
column 'Price' do |artwork|
artwork.transactions.map do |transaction|
transaction&.price
end
end
column 'Currency' do |artwork|
artwork.transactions.map do |transaction|
transaction&.currency
end
end
end
end
# rubocop:enable Metrics/BlockLength
It is the last three columns that are not giving me the correct information.
For underbidders, I receive the term "Investor" in all rows. The multiple investor names show up fine in the admin page itself, but not in the CSV export. There could be multiple names so perhaps that is the issue. I've tried several different variations.
If I use column('Underbidders', &:underbidders) as in the index, I get an output that isn't readable on a CSV.
For Price and Currency, this comes from the Transactions table. For price I get items such as [1800000, 1800000, 1800000] and for currency, I get ["usd", "USD"] instead of the one item it should be and without the brackets. They are the same items (for each transaction, the amount and currency is repeated for each investor (buyer and underbidder), but it should only be one final for each transaction.

The Price & Currency make sense -- .map is iterating through a list, applying that function to each member of the list, and returning the list with that function applied.
The problem with that is you are expecting only one value but are getting a list back. Instead, since you don't care about which item in the list, you can grab the first one and its attribute:
column 'Price' do |artwork|
artwork.transactions.first&.price
end
column 'Currency' do |artwork|
artwork.transactions.first&.currency
end
The Underbidders issue is more domain-specific. Have you checked that the method name in app/models/underbidders.rb is actually returning something other than Investor? It may also be a column in the database that is just filled with the value Investor. Or maybe it's a class name.
Since row('Underbidders', &:underbidders) works above, I think this may mean that def to_s is implemented for Underbidder and simply returns the name of the underbidder that you're expecting. You could try:
column 'Underbidders' do |artwork|
artwork.underbidders&.to_s
end

Related

active admin how to display name of collection select insted of id

I got this error
undefined method `name' for #<Array:0x00007fb013333018>
I need to display product name
f.input :product_ids , :as => :select, :collection => Product.all.collect {|product| [product.name, product.id] }
here is my codes
ActiveAdmin.register Case do
permit_params :user_id, :product_ids ,:step_ids , :pt_first_name,:pt_last_name, :date_received, :due_date, :shade,
:mould, :upper_lower
index do
column do |user|
link_to :id, doctor_path(user.id)
end
column :pt_first_name
column :pt_last_name
column "product" do |m|
u=Product.find(m.product_ids).name
end
column :user
column :product
column :sign_in_count
column :created_at
actions
end
form do |f|
f.inputs do
f.input :user
f.input :pt_first_name
f.input :pt_last_name
f.input :date_received
f.input :due_date
f.input :shade
f.input :mould
f.input :upper_lower
f.input :product_ids , :as => :select, :collection => Product.all.collect {|product| [product.name, product.id] }
f.input :step_ids , :as => :select, :collection => Step.all.collect {|step| [step.name, step.id] }
end
actions
end
end
u=Product.find(m.product_ids).name
product_ids is array of product ids.
.find will returns an array for objects if you pass multiple ids or array of ids, so .name will not directly work on result as it array.
you can use either of following options
Using find & map
column "product" do |m|
Product.find(m.product_ids).map(&:name).join(', ')
end
Using where & map
column "product" do |m|
Product.where(id: m.product_ids).map(&:name).join(', ')
end
Using where & pluck
column "product" do |m|
Product.where(id: m.product_ids).pluck(:name).join(', ')
end
Using Rails 6.0.0 on MRI 2.6.3, this worked for me:
f.select :product_ids, Product.all.collect { |prod| [prod.name, prod.id] }, {}, { multiple: true }

Ruby on Rails and ActiveAdmin: add all object all at once instead add one by one

I'm using Ruby on Rails 5 API app with Active Admin.
I have a model called Subscription with has_many courses (Course is also a model).
When I add courses to a subscription, I need to do it one by one, like in this picture:
What I want is to have an option to add all the courses to a subscription all at once, instead of one by one. I tried using checkbox for multiple selection but it didn't worked. This is the code:
ActiveAdmin.register Subscription do
# require 'lib/app_languages.rb'
permit_params :name, :seat_limit, :domain, :language, :organization, course_ids: [], user_ids: [], subscription_courses_attributes: [:id, :course_id, :_destroy, :_create, :_update]
config.sort_order = 'id_asc'
# Index
index do
id_column
column :name
column :seat_limit
column :domain
column :organization
column :language do |subscription|
AppLanguages.languages[subscription.language]
end
column "Unlocked courses", :courses
column :created_at
actions
end
# Show
show do
attributes_table do
row :name
row :language do |subscription|
AppLanguages.languages[subscription.language]
end
row :seat_limit
row :domain
row :organization
row :created_at
end
panel 'Unlocked Courses' do
table_for subscription.courses do
column :id
column "Title" do |course|
link_to course.title, admin_course_path(course)
end
column "language" do |course|
AppLanguages.languages[course.language]
end
column :author
end
end
panel 'Subscribed users' do
table_for subscription.users do
column :id
column "name" do |user|
link_to user.name, admin_user_path(user)
end
column :email
column "language preference" do |user|
AppLanguages.languages[user.language]
end
end
end
end
# Edit
form do |f|
f.semantic_errors *f.object.errors.keys
f.inputs 'Details' do
f.input :name
f.input :language, :as => :select, :collection => AppLanguages.languages_array
f.input :seat_limit
f.input :domain
f.input :organization
end
f.has_many :subscription_courses do |sub_c|
sub_c.inputs "Unlocked Courses" do
if !sub_c.object.nil?
sub_c.input :_destroy, as: :boolean, label: "Destroy?"
end
sub_c.input :course ### should add here option for add all
end
end
f.inputs 'Subscribed users:' do
f.input :users
end
f.actions
end
end
Using for the array the as: :select form input with multi-select should help. Something like this:
sub_c.input :items, as: :select,
collection: courses_collection,
multiple: true
You can try using check_boxes
sub_c.input :items, as: :check_boxes, collection: courses_collection

Active Admin remove certain fields while going for updation

Hi i have an admin page using active admin gem.
thing is while creating a new page i should be able to input name, amount and interval..But while updating only name field must show..other 2 values shouldnt be updated. This is my active admin file. How to make this happen. Thanks in advance
ActiveAdmin.register SubscriptionPlan do
menu priority: 10
permit_params :name, :amount, :interval
index do
selectable_column
default_actions
column :name
column :amount
column :interval
end
form do |f|
f.inputs "Subscription Plan" do
f.input :name
f.input :amount
f.input :interval, as: :select, collection:["week","month","year"]
end
f.actions
end
end
Try this
form do |f|
f.inputs "Subscription Plan" do
f.input :name
if f.object.new_record?
f.input :amount
f.input :interval, as: :select, collection:["week","month","year"]
end
end
f.actions
end

How can I rectify ActiveRecord::Associations::CollectionProxy

I am creating a category select dropdown to add categories to an event.
I can add them and they are showing in the form for the edit area, I can see the categories added in the backend.
When I try to show them in the views it gives me this strange error inside the layout:
<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Category:0x00000102542f10>
In my setup I have got this:
views/events/index.html.erb
<%=
event.categories.each do |events|
category.name
end
%>
models/category.rb
class Category < ActiveRecord::Base
belongs_to :event
belongs_to :profile
belongs_to :classified
belongs_to :page
extend FriendlyId
friendly_id :name, use: :slugged
end
admin/category.rb
ActiveAdmin.register Category do
controller do
def permitted_params
params.permit category: [:name, :description]
end
def find_resource
scoped_collection.friendly.find(params[:id])
end
end
form do |f|
f.inputs "Name" do
f.input :name
end
f.inputs "Description" do
f.input :description, :as => :ckeditor, :label => false, :input_html => { :ckeditor => { :toolbar => 'Full', :height => 400 } }
end
f.actions
end
end
In my categories table there is an event_id column in there so it can fnd the associated event and it links to both the events table and the categories table.
Any insight into this would be great
Thanks
Update views/events/index.html.erb as below:
<% if event.categories.count > 0 %>
<% event.categories.each do |category| %> ## Use <% %> to evaluate ruby code
<%= category.name %> ## Use <%= %> To evaluate and show the results
<% end %>
<% end %>
In your case, <%= %> will return event.categories value which is an instance of <ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Category which is what you see on the rendered page.
UPDATE
OP also had foreign_key concerns. Add foreign_keys for event, profile, classified and page in categories table.

Creating a record with Associations - Active Admin

I am using active admin and seem to be struggling with creating a record with an association. I have set this up in the normal way
class Membership < ActiveRecord::Base
belongs_to :member
attr_accessible :membership_type
end
class Member < ActiveRecord::Base
has_one :membership
accepts_nested_attributes_for :membership
attr_accessible :membership_attributes, :forename, :middlename, :surname, :house_no, :house_name, :street, :town, :postcode, :home_tel, :mobile_tel, :work_tel, :email
end
I then want to create a New member along with their membership type in the same form, so my member.rb looks like this so far
ActiveAdmin.register Member do
# Set Which Columns are to be displayed on the index page
index do
column :forename
column :middlename
column :surname
column :house_no
column :house_name
column :street
column :town
column :postcode
column :home_tel
column :mobile_tel
column :work_tel
column :email
column :membership do |member|
member.membership.map{ |ms| ms.membership_type}
end
default_actions
end
# Set Which Columns are to be displayed on Create New Member
form do |f|
f.inputs "Member Registration" do
f.input :forename
f.input :middlename
f.input :surname
f.input :house_no
f.input :house_name
f.input :street
f.input :town
f.input :postcode
f.input :home_tel
f.input :mobile_tel
f.input :work_tel
f.input :email
end
f.inputs :for => [:membership, f.object.membership || Membership.new] do |m|
m.input :membership_type, :label => 'Membership Type', :as => :select, :collection => Membership.all.map{|m| [m.membership_type]}
end
f.actions
end
end
This displays a select box where i can choose from various Membership types, but i dont seem to be passing the correct value when creating the record,
This is an example of what is being posted
member[forename]:Name 1
member[middlename]:Name 2
member[surname]:Name 3
member[house_no]:1
member[house_name]:
member[street]:Test Street
member[town]:Test Town
member[postcode]:CF23 7BD
member[home_tel]:01633222222
member[mobile_tel]:07864582356
member[work_tel]:01633555555
member[email]:test#mail.com
membership_attributes"=>{"membership_type"=>"Student"}
commit:Create Member
This doesn't seem right does it? Also when i try and view the record
column :memberships do |member|
member.memberships.map{ |ms| ms.membership_type}
end
I get the following mysql error
Mysql2::Error: Unknown column 'memberships.member_id' in 'where clause': SELECT `memberships`.* FROM `memberships` WHERE `memberships`.`member_id` = 10
Could anyone point me in the right direction please or can anyone see where im going wrong?
Much appreciated
Instead of f.input :memberships try this:
f.has_many :memberships do |pf|
pf.input :membership_type
end
and close your member object fields like this
f.inputs "Member Registration" do
f.input :forename
f.input :middlename
f.input :surname
...
end
So your form should look like this:
form do |f|
f.inputs "Member Registration" do
f.input :forename
f.input :middlename
f.input :surname
# .. the rest of your fields
end
f.has_many :memberships do |pf|
pf.input :membership_type
end
f.actions
end
Regarding the MySQL error, i think for the association to work you need to add the column member_id to the memberships table. You can create the migration with
rails g migration add_member_id_to_memberships member_id:integer
Then migrate with
bundle exec rake db:migrate

Resources