active admin how to display name of collection select insted of id - ruby-on-rails

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 }

Related

Custom CSV Export in Active Admin Index Page Problems

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

filter dropdown appear as object in Active Admin in rails 5

ActiveAdmin.register Type do
permit_params :name, :job, version_ids: []
index do
id_column
column :name
column :job
column :versions do |type|
type.versions.collect(&:name).join(', ')
end
actions
end
form(html: { multipart: true }) do |f|
f.inputs do
f.input :name, as: :string
f.input :job, as: :string
f.input :versions, as: :select, input_html: { multiple: true }
end
f.actions
end
end
This table has a has_many relation with workers table. The dropdown which shows the worker filter shows the worker object instead of the worker name. How can I get the worker name in the dropdown instead of the worker object.
Try:
f.input :versions, as: :select,
collection: versions.pluck(:name, :id),
input_html: { 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

while selecting multiple options from dropdown list in active admin table

while selecting multiple options from dropdown list in active admin table
multiple selected items are not showing in index file
form do |f|
inputs 'Contact Group' do
#f.input :contact_id, as: :select, collection: Contact.all, multiple: true
#f.input :contact_id, as: :select, collection: Contact.select(:name).uniq,multiple: true
f.input :contact_id, as: :select, :collection => Contact.all.collect {|contact| [contact.name, contact.id] }, multiple: true
f.input :name
f.input :disable
end
actions
end
index do
id_column
column :contact_id
column :name
column :disable
actions
end

ActiveAdmin how to display values in dropdown but store keys to db

How can I display the string name, but save the integer key to the db in a dropdown in active admin?
I have this form:
form do |f|
f.inputs "Status" do
f.input :status, as: :select, collection: App::STATUSES.keys
end
f.actions
end
which produces this and works fine:
but I need it to produce this:
This is the code which produces the above image. It displays the values that I want, but it doesn't save the keys (0, 1, 2, etc.) to the db
form do |f|
f.inputs "Status" do
f.input :status, as: :select, collection: App::STATUSES.values
end
f.actions
end
I tried this but it doesn't work:
form do |f|
f.inputs "Status" do
f.input :status, as: :select, collection: App::STATUSES.values, :label_method => :status_name
end
f.actions
end
Here is my model:
IN_PROGRESS = 0 #default
SUBMITTED = 1
REVIEW = 2
PENDING = 3
APPROVED = 4
LIVE = 5
STATUSES = {
IN_PROGRESS => 'in progress',
SUBMITTED => 'submitted',
REVIEW => 'review',
PENDING => 'pending',
APPROVED => 'approved',
LIVE => 'live'
}
def status_name
STATUSES[status].to_s
end
The status_name method works fine throughout my app, it just doesn't get called for some reason when displaying the dropdown.
try use your hash as collection (or inverted hash)
f.input :status, as: :select, collection: App::STATUSES.invert, :label_method => :status_name

Resources