Active Admin checkboxes not selected when edit model - ruby-on-rails

I'm using a custom collection to display checkboxes with schedule. It saves, but when I try to edit it returns to me unchecked. Why?
f.inputs for: :schedule, name: 'Employee Schedule' do |sf|
sf.input :sunday, as: :check_boxes, collection: available_hours, method: :to_s
sf.input :monday, as: :check_boxes, collection: available_hours, method: :to_s
sf.input :tuesday, as: :check_boxes, collection: available_hours, method: :to_s
sf.input :wednesday, as: :check_boxes, collection: available_hours, method: :to_s
sf.input :thursday, as: :check_boxes, collection: available_hours, method: :to_s
sf.input :friday, as: :check_boxes, collection: available_hours, method: :to_s
sf.input :saturday, as: :check_boxes, collection: available_hours, method: :to_s
end
def available_hours
(0..23).map { |h| ["#{h}h às #{h.next}h", h] }
end
helper_method :available_hours

I found a solution for this question
My collection remains unaltered
def available_hours
Array(0..23)
end
And my form will have a :member_label parameter receiving a Proc that will change it after collection already gathered
member_label: Proc.new { |h| "#{h}h às #{h.next}h" }
After modifications:
sf.input :sunday, as: :check_boxes, collection: available_hours, member_label: Proc.new { |h| "#{h}h às #{h.next}h" } , method: :to_s
and so on...

You need to determine which checkbox is selected like this: ["#{h}h às #{h.next}h", h, :selected]
def available_hours(_h)
(0..23).map { |h| ["#{h}h às #{h.next}h", h, h == _h ? :selected : ''] }
end
sf.input :sunday, as: :check_boxes, collection: available_hours(sh.object.sunday), method: :to_s
...or something similar.

It could be a different situation/need, but I think what I did for one of my project is possible a solution. I created a custom FormStatic input class that can be used for an ActiveAdmin edit form.
module ActiveAdmin
module Inputs
class ProductsInput < ::Formtastic::Inputs::CheckBoxesInput
def choice_html(choice)
html_options = label_html_options.merge(
:for => choice_input_dom_id(choice),
:class => checked?(choice[1]) ? 'checked' : nil
)
template.content_tag(:label, choice_label(choice), html_options)
end
def collection
super.sort {|a, b| a[0] <=> b[0]}
end
def choice_label(choice)
name, id = choice
product = Product.find(id)
name = ''
name << template.content_tag(:span, product.human_state_name, class: 'status_tag important') + ' ' unless product.on_sale?
name << product.name
(hidden_fields? ?
check_box_with_hidden_input(choice) :
check_box_without_hidden_input(choice)) + \
template.image_tag(product.listing.thumb, width: 60).html_safe + \
template.content_tag(:span, name.html_safe, class: 'choice_label')
end
end
end
end
Then you can use it in an edit block like this:
ActiveAdmin.register Collection do
form do |f|
f.inputs 'Products' do
f.input :products, as: :products
end
end
end
Collection has_many products through collection_products.

Related

Use activeadmin-ajax_filter gem in nested forms

I'm using ActiveAdmin for an admin panel. In the nested form, I need to use some filtering, for example, in the dropdown I need to select an option name, and in the second dropdown should be displayed the option's values.
For this, I want to use activeadmin-ajax_filter gem. Option and OptionValue are connected with each other: Option has_many :option_values, and OptionValue belongs_to Option. I create option_values through the nested form when I create the Option.
Then, I have a Product model, in which via nested form I create a Variant. So, Variant belongs_to :option_value belongs_to :product and OptionValue has_many :variants, Product has_many :variants.
Just for now, when I want to create a new variant, I can select all the option values I have in the db. I want to select an option (for example a size), and then, in a dropdown below - select the appropriate values (XL, S, and so on).
The code for my active_admin resources is:
ActiveAdmin.register Product do
permit_params :category_id, :name, :description, :short_description, :image, :subtitle,
product_currencies_attributes: [:id, :product_id, :currency_id, :price, :_destroy],
variants_attributes: [:id, :product_id, :in_stock_id, :sold_out_id, :option_value_id, :image, :visible,
:orderable, :_destroy]
index do
column :id
column :image do |product|
image_tag(product.image.url(:thumb)) if product.image
end
column :category_id do |product|
category = Category.find(product.category_id)
link_to category.name, admin_category_path(category)
end
column :name
column :short_description
column :description do |product|
product.description.truncate(90)
end
column :subtitle
column :created_at
column :updated_at
actions
end
show do
tabs do
tab 'Product' do
attributes_table do
row :id
row :image do
image_tag(product.image.url(:medium))
end
row :category_id do
category = Category.find(product.category_id)
link_to category.name, admin_category_path(category)
end
row :name
row :short_description
row :description
row :subtitle
row :created_at
row :updated_at
end
end
tab 'Prices' do
attributes_table do
row :prices do
div do
product.product_currencies.each do |product_currency|
div do
"#{Currency.find(product_currency.currency_id).name}: #{product_currency.price}"
end
end
end
end
end
end
tab 'Variants' do
div do
'Variants will be here soon =)'
end
end
end
end
form do |f|
tabs do
tab 'Product' do
f.inputs do
f.input :category_id, as: :select, collection: Category.all.collect { |category| [category.name, category.id] }
f.input :name
f.input :short_description
f.input :description
f.input :subtitle
f.input :image, as: :file
end
end
tab 'Price' do
f.inputs do
f.has_many :product_currencies, allow_destroy: true, heading: false, new_record: 'Add New Price' do |product_currency|
product_currency.template.render partial: 'product-price-form', locals: { product_currency: product_currency,
product_id: params[:id].to_i }
end
end
end
tab 'Variants' do
f.inputs do
f.has_many :variants, allow_destroy: true, heading: false, new_record: 'Add new Variant' do |variant|
variant.template.render partial: 'variant-form', locals: { variant: variant, product_id: params[:id].to_i }
end
end
end
tab 'SEO' do
div do
'SEO inputs will be here'
end
end
end
f.actions
end
end
So, I've installed activeadmin-ajax_filter gem. I tried to follow the documentation, but as a result - nothing. As far, as I understand, I have to put this line of code to my Option activeadmin model: activeadmin-ajax_filter, and in the form use this:
f.input :option, as: :ajax_select, data: {
url: filter_admin_options_path,
search_fields: [:name],
static_ransack: { active_eq: true },
ajax_search_fields: [:option_value_id],
}
But still - nothing. By the way, the partial is:
<% if #product.new_record? %>
<% if Product.any? %>
<% new_product_id = Product.order(id: :desc).first.id + 1 %>
<% variant.input :product_id, as: :hidden, input_html: { value: new_product_id } %>
<% else %>
<% variant.input :product_id, as: :hidden, input_html: { value: 1 } %>
<% end %>
<% else %>
<% variant.input :product_id, as: :hidden, input_html: { value: product_id } %>
<% end %>
<% variant.input :in_stock_id, as: :select, collection: InStock.all.collect { |in_stock| [in_stock.name, in_stock.id] } %>
<% variant.input :sold_out_id, as: :select, collection: SoldOut.all.collect { |sold_out| [sold_out.name, sold_out.id] } %>
<%# variant.input :option, as: :ajax_select, collection: Option.all.collect { |option| [option.name, option.id] },
# data: {
# url: filter_admin_options_path,
# serarch_fields: [:name],
# static_ransack: { active_eq: true },
# ajax_search_fields: [:option_value_id]
# }
#%>
<% variant.input :option_value_id, as: :select, collection: OptionValue.all
.collect { |option_value| [option_value.value, option_value.id] } %>
<% variant.input :visible %>
<% variant.input :orderable %>
<% variant.input :image, as: :file %>

first element in form can't be blank

I've got this problem
.container.weekdays
.row
.col-sm-3
.panel-default data-day="#{#weekdays[0]}"
.h3
|Today's menu.
=#weekdays[0]
br
=link_to "Today's menu", admin_menu_path("#{#weekdays[0]}"), class: 'today', remote: true
hr
hr
fieldset
legend Update menu here
=form_for [:admin, #menu] ,method: :patch, remote: true do |f|
p
= f.select(:type, options_for_select(["", :First, :Second, :Drink], include_blank: true))
p
=f.label 'Name'
=f.text_field :name
p
=f.label 'Price'
=f.number_field :price
= f.submit
and menus controller, where show action is working right
class Admin::MenusController < Admin::BaseController
before_action :set_menu , only:[:update]
def show
#menu = Menu.where(day: params[:id])
end
def update
#menu = Menu.where(day: DateTime.now.strftime("%A"))
#item = menu_params.type.constantize.new(name: menu_parms.name, price: params[:menu][:price], menu: #menu)
#item.save
end
private
def menu_params
params.require(:menu).permit(:type, :name, :price)
end
end
I am recieving first argument cn't be nill in form update, need some help n that. I do undestand that code is awful but still I am a newcommer it should work first than I'll try to refact
To better understand the problem here is menu model
class Menu < ApplicationRecord
has_many :dishes
delegate :firstmeals, :secondmeals, :drinks, to: :dishes
validates :day, presence: true
validates :day, uniqueness: true
def self.get_menu day
Menu.where(day: day).first
end
private
def to_param
day
end
end
So I do not actually need to update menu, I need only to create a dish. But the same problemm still exist
fieldset
legend Update menu here
=form_for [:admin, #dish], method: :patch, remote: true do |f|
p
= f.select(:type, options_for_select(["", :First, :Second, :Drink], include_blank: true))
p
=f.label 'Name'
=f.text_field :name
p
=f.label 'Price'
=f.number_field :price
= f.submit
include_blank should be outside of options_for_select
= f.select(:type, options_for_select([:First, :Second, :Drink]), { include_blank: true })
If you are passing include_blank option you don't need to add empty string manually
documentation for select

Active Admin - Can I add a Data Attribute to the Form Tag?

I need to add a data attribute to a form tag created by Active Admin.
Here is the current Active Admin form code ...
ActiveAdmin.register Pdf do
menu parent: "Video Series"
PDFTYPES = {
outline: "Outline",
transcript: "Transcript"
}
member_action :getvideos do
unless params[:id].blank?
render :json => Video.where(video_series_id: params[:id]).to_json.html_safe
end
end
member_action :clearvideo do
#binding.pry
#puts "pdfID : #{id}"
end
index do
column :title
column :description
column :pdf_type
column :created_at
column :updated_at
actions
end
form do |f|
f.inputs "Pdf Content" do
f.input :title
f.input :url
f.input :description
f.input :pos
f.input :video_series, as: :select, include_blank: true, collection: VideoSeries.all.map { |video| ["#{video.title}", video.id] }
f.input :pdf_type, as: :select, include_blank: true, collection: PDFTYPES.sort.map {|key,val| [val,key]}, input_html: { data: {pdf_id: pdf.id} }
f.input :video, as: :select, include_blank: true, collection: Video.where(video_series_id: f.object.video_series_id).map { |video| ["#{video.title}", video.id] }
f.actions
end
end
end
You can see in my code above how I create a data attribute on the second select input named "pdf_type" - "input_html: { data: {pdf_id: pdf.id} }."
I would like this data attribute on the form tag. Can this be done with Active Admin?
Thanks,
Chris
You can do this that way
form html: { data: { attribute: 'value' } } do |f|
# Your code goes there
...
end

Extract search functionality to Form Object in Rails

In my Rails application I have simple search functionality. I want to extract to Form Object but don't know how to do. I have search form which looks like this:
.row
= horizontal_simple_form_for :cars, {url: cars_path, method: :get} do |f|
.col-md-4
.row
.col-md-12
= f.input :handover_location, label: I18n.t('.handover'), collection: Location.all.map{|hl| [hl.location_address, hl.id]}
= f.input :return_location, label: I18n.t('.return') ,collection: Location.all.map{|rl| [rl.location_address, rl.id]}
= f.input :car_class, label: I18n.t('.car_class') ,collection: CarClass.all.map { |c| [c.name, c.id] }, include_blank: true
.col-md-4
= f.input :handover_date, as: :string, label: false
= f.input :return_date, as: :string, label: false
= f.submit class: 'btn btn-success'
Cars controller:
class CarsController < ApplicationController
skip_authorization_check
def index
#cars = Car.search(params)
end
def show
end
end
And class method in Car model which search correct cars:
def self.search(params)
self.joins(:reservations).where.not("reservations.reception_time <= ? AND reservations.return_time >= ?",
params[:cars][:return_date], params[:cars][:handover_date]).
joins(:car_class).where("car_classes.id= ?", params[:cars][:car_class])
.cars_at_both_locations(params[:cars][:handover_location], params[:cars][:return_location])
end
Now I'm trying to extract this to Form Object. I've created a file search_form.rb:
class SearchForm
include ActiveModel::Model
attr_accessor :handover_date, :return_date, :handover_location, :return_location, :car_class
end
But now I don't know how to handle my params to this form object. Thank's in advance.
I wish I could help you with the Form Object stuff, but I need to learn more about classes & modules
I can help you with the search functionality, as we've done it before here
Here's the code we used:
#View
<%= form_tag search_path, :method => :post, :id => "SearchForm" do %>
<%= text_field_tag :search, params[:search], placeholder: 'Search your favourite products or brands', :autocomplete => :off %>
<%= image_submit_tag 'nav_bar/search.png' %>
<% end %>
#config/routes.rb
match 'search(/:search)', :to => 'products#search', :as => :search, via: [:get, :post]
#app/controllers/products_controller.rb
def search
#products = Product.search(params[:search])
respond_to do |format|
format.js { render :partial => "elements/livesearch", :locals => {:search => #products, :query => params[:search]} }
format.html { render :index }
end
end
Notice the form_tag we used?
Simple form does not work with form_tag currently (it requires an object) - we just send the data with a GET request to the controller & that then sends the data to the Product model
I think your problem will be caused by the use of your SearchForm object. You only need this because your use of simple form means you have to pass an object. Problem being this is not necessary for search
A better way will be to use a standard form_tag, and send the request directly to your controller. This will allow you to process the data as params, which you'll be able to send directly to your Car model
--
I can write some code specific to you if you want
I found solution on my own.
Cars controller:
def index
#search_form = SearchForm.new(params[:search_form])
#cars = #search_form.submit(params[:search_form])
end
search_form.rb:
class SearchForm
include ActiveModel::Model
attr_accessor :handover_date, :return_date, :handover_location, :return_location, :car_class
def submit(params)
Car.search(params)
end
end
Search form in view:
.row
= horizontal_simple_form_for SearchForm.new, {url: cars_path, method: :get} do |f|
.col-md-4
.row
.col-md-12
= f.input :handover_location, label: I18n.t('.handover'), collection: Location.all.map{|hl| [hl.name, hl.id]}
= f.input :return_location, label: I18n.t('.return') ,collection: Location.all.map{|rl| [rl.name, rl.id]}
= f.input :car_class, label: I18n.t('.car_class') ,collection: CarClass.all.map { |c| [c.name, c.id] }, include_blank: true
.col-md-4
= f.input :handover_date, as: :string, label: false
= f.input :return_date, as: :string, label: false
= f.submit class: 'btn btn-success'
search method in car model:
def self.search(params)
self.joins(:reservations).where.not("reservations.reception_time <= ? AND reservations.return_time >= ?",
params[:return_date], params[:handover_date]).
joins(:car_class).where("car_classes.id= ?", params[:car_class])
.cars_at_both_locations(params[:handover_location], params[:return_location])
end

Make select list output in alphabetical order in Rails?

I have a select list in my model which lists a persons name with their employers name:
<li>Case Handler Name<span><%= f.select :person_id, Person.all.collect { |x| [x.name_and_company, x.id] } %></span></li>
def name_and_company
return "#{personname} (#{company})"
end
Is it possible to force the select list to output in alphabetical order?
I am assuming I would put an order tag in there...somewhere?
(:order => 'personname DESC')
Thanks,
Danny
You can do it like this
# controller
#people = Person.order_by('personname ASC').collect {|x| [x.name_and_company, x.id] }
# model
named_scope :order_by, lambda { |o| {:order => o} }
# view
<%= f.select :person_id, #people %>
Answer:
#users_controller.rb
def index
#people = Person.alphabetically
end
#user.rb
scope :alphabetically, order("name ASC")
#index.haml
= f.select :person_id, #people.all.collect { |p| [p.name, p.id] } %>
Even easier ...
<%= f.select :name, options_from_collection_for_select(Person.order("name ASC"), :name, :name), :prompt => 'Select' %>
Note: Doesn't require custom methods or additions to controller

Resources