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.
CodePudding user response:
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