Let's say I have a model:
class User
has_many :books
end
class Book
belongs_to :user
end
Now in active admin, I want when I select any user. The form will only display books created by that user.
forms do |f|
f.inputs do
f.input :user, as: :select, collection: User.all
f.input :books, as: :select, collection: Book.all
end
f.actions
end
What is the query to replace Book.all?
This work for me on dependend "select" on Rails 6.0.4
Models
class Organization < ApplicationRecord
belongs_to :sector
belongs_to :sub_sectors
end
class Sector < ApplicationRecord
has_many :sub_sectors
end
class SubSector < ApplicationRecord
belongs_to :sector
end
Active admin form
ActiveAdmin.register Organization do
form do |f|
f.inputs "Details" do
f.input :sector, as: :select, collection: Sector.all
f.input :sub_sector_id, as: :select, collection: ([]) # The input is initialized without values
end
f.actions
end
end
You must do the following:
Create a controller, that returns the subsectors.
class SubSectorsController < ApplicationController
def sub_sectors_filter
if params[:sector_id]
sector = Sector.find(params[:sector_id])
#sub_sectors = sector.sub_sectors
else
#sub_sectors = []
end
render :json => #sub_sectors.collect {|sub_sector| {:id => sub_sector.id, :name => sub_sector.name} }
end
end
Add the route in the routes.rb file.
get 'sub_sectors_filter/' => 'sub_sectors#sub_sectors_filter'
Inspect with your web browser console your selects, and use a CSS selector to create a jQuery object for the sector select, something like:
$('#organization_sector_id')
Add this block of code in the file /app/assets/javascripts/active_admin.js, which is responsible for making the call to the generated controller, and adding the options that it returns.
//= require active_admin/base
$(function () {
$('#organization_sector_id').on('change', function () {
$('#organization_sub_sector_id option').remove(); // Remove all <option> child tags.
$.getJSON(`/sub_sectors_filter`, {sector_id: $(this).val()}, function(result){ // Documentation on getJSON: http://api.jquery.com/jQuery.getJSON/
$.each(result, function (i, item) { // Iterates through a collection
$('#organization_sub_sector_id').append($('<option>', { // Append an object to the inside of the select box
value: item.id,
text : item.name
}));
});
});
})
})
References:
Can't find the error in my dependent select drop down on Active Admin( Rails 3.2, Active Admin 1.0)
Populate Select box options on click with Javascript/Jquery with Json data
As Sampat mentioned in the comment you can use ActiveAdmin nested select addon.
After installing activeadmin_addons gem, you can use:
forms do |f|
f.inputs do
f.input :user_id, as: :nested_select,
level_1: { attribute: :user_id, collection: User.all },
level_2: { attribute: :book_id, collection: Book.all }
end
f.actions
end
Related
I have three models:
class Request < ActiveRecord::Base
belongs_to :scenario
belongs_to :location
has_many :actions, :foreign_key => 'request_id'
accepts_nested_attributes_for :actions, :allow_destroy => true
end
class Action < ActiveRecord::Base
belongs_to :request
belongs_to :scenario_step
end
class ScenarioStep < ActiveRecord::Base
belongs_to :scenario
has_many :actions
end
Using Active Admin I want to update information about action taken in response to a request. To do that I am using nested form:
ActiveAdmin.register Request do
permit_params :scenario_id, :location_id,
actions_attributes: [:scenario_step_id, :description]
form(:html => {:multipart => true}) do |f|
f.inputs "Request details" do
f.input :status
panel 'Steps' do
"Text ..."
end
f.has_many :actions, heading: 'Steps to follow', allow_destroy: false, new_record: true do |ff|
ff.input :description, label: ff.object.scenario_step_id, hint: 'Text'
ff.input :scenario_step_id
end
para "Press cancel to return to the list without saving."
f.actions
end
end
end
Everything seems to be fine except of label (or hint). As a value I want to put there related data from a table scenario_steps.
As you can see I currently try to at least print the value of scenario_step_id that should be available in the object form (ff.object.scenario_step_id) but it is not working (I have such column in actions table). On the other hand, next line: ff.input :scenario_step_id loads appropriate data into input field.
Can somebody give ma a hint what am I doing wrong?
Here is what I was missing (part of formtastic documentation):
Values for labels/hints/actions are can take values: String (explicit
value), Symbol (i18n-lookup-key relative to the current "type", e.g.
actions:), true (force I18n lookup), false (force no I18n lookup).
Titles (legends) can only take: String and Symbol - true/false have no
meaning.
So small change (to_s) in line below makes huge difference :)
ff.input :description, label: ff.object.scenario_step_id.to_s, hint: 'Text'
Using ActiveAdmin with Rails 4, I have two models, Document and Attachment with a one-to-many relationship between them.
# models/document.rb
class Document < ActiveRecord::Base
has_many :attachments
accepts_nested_attributes_for :attachments
end
# models/attachment.rb
class Attachment < ActiveRecord::Base
belongs_to :document
end
I registered the models and included permit_params for all the fields in each.
Now I used has_many in the form view in the below code. This shows an option to add Attachments and it work just fine.
# admin/document.rb
ActiveAdmin.register Document do
permit_params :title, :description, :date, :category_id
show do |doc|
attributes_table do
row :title
row :description
row :attachments do
doc.attachments.map(&:document_path).join("<br />").html_safe
end
end
end
form do |f|
f.inputs "Details" do
f.input :title
f.input :description
f.input :category
f.has_many :attachments, :allow_destroy => true do |cf|
cf.input :document_path # which is a field in the Attachment model
end
end
f.actions
end
end
However, when I submit the form, the document object is saved but no attachment objects are saved with it. As much as I understand it should create as many attachments I added in the form and pass in their document_id attribute the created document ID. Unfortunately this is not happening leaving the Attachment row "EMPTY" in the show view. Am I missing something?
Thanks in advance.
You forgot to permit attachments_attributes.
In order to use accepts_nested_attribute_for with Strong Parameters, you will need to specify which nested attributes should be whitelisted.
More info http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html
I use Active Admin gem for Ruby on Rails.
I have modules Team and Coach, which have a has_many and belongs_to relationship.
class Team < ActiveRecord::Base
belongs_to :coach
end
class Coach < ActiveRecord::Base
has_many :teams
end
I figured out how to display first name and last name on index and show page (i did it like that:)
index do
column :name
column "Coach" do |team|
team.coach.firstname + " " + team.coach.lastname
end
default_actions
end
What i want is how to display first name and last name of coach in Team form (new and edit page) in dropdown menu?
Please help me with this.
Can you try this
f.input :coach_name, :as => :select, :collection => Coach.all.map {|u| [u.firstname, u.id]}, :include_blank => false
I had the same problem. The edit page shows object instances in the select menu such as,
#<Coach:0x00eff180c85c8>
To solve it and access each instance's fields use this,
form do |f|
f.inputs "Coaches" do
f.input :name
f.input :coach, member_label: Proc.new { |c| "#{c.firstname} #{c.lastname}"
end
f.actions
end
ActiveAdmin uses Formtastic and its documentation has more examples.
This stackoverflow answer helped me get this solution.
Try this:
f.input :coach_name, :as => :select, :collection => Coach.all.map {|u| [u.firstname.to_s, u.id]}
We are using active_admin for our administration backend.
We have a model "App" that :belongs_to model "Publisher":
class App < ActiveRecord::Base
belongs_to :publisher
end
class Publisher < ActiveRecord::Base
has_many :apps
end
When creating a new entry for the "App" model I want to have the option to either select an existing publisher or (if the publisher is not yet created) to create a new publisher in the same (nested) form (or at least without leaving the page).
Is there a way to do this in active_admin?
Here's what we have so far (in admin/app.rb):
form :html => { :enctype => "multipart/form-data" } do |f|
f.inputs do
f.input :title
...
end
f.inputs do
f.semantic_fields_for :publisher do |p| # this is for has_many assocs, right?
p.input :name
end
end
f.buttons
end
After hours of searching, I'd appreciate any hint... Thanks!
First, make sure that in your Publisher model you have the right permissions for the associated object:
class App < ActiveRecord::Base
attr_accessible :publisher_attributes
belongs_to :publisher
accepts_nested_attributes_for :publisher, reject_if: :all_blank
end
Then in your ActiveAdmin file:
form do |f|
f.inputs do
f.input :title
# ...
end
f.inputs do
# Output the collection to select from the existing publishers
f.input :publisher # It's that simple :)
# Then the form to create a new one
f.object.publisher.build # Needed to create the new instance
f.semantic_fields_for :publisher do |p|
p.input :name
end
end
f.buttons
end
I'm using a slightly different setup in my app (a has_and_belongs_to_many relationship instead), but I managed to get it working for me. Let me know if this code outputs any errors.
The form_builder class supports a method called has_many.
f.inputs do
f.has_many :publisher do |p|
p.input :name
end
end
That should do the job.
Update: I re-read your question and this only allows to add a new publisher, I am not sure how to have a select or create though.
According to ActiveAdmin: http://activeadmin.info/docs/5-forms.html
You just need to do as below:
f.input :publisher
I've found you need to do 3 things.
Add semantic fields for the form
f.semantic_fields_for :publisher do |j|
j.input :name
end
Add a nested_belongs_to statement to the controller
controller do
nested_belongs_to :publisher, optional: true
end
Update your permitted parameters on the controller to accept the parameters, using the keyword attributes
permit_params publisher_attributes:[:id, :name]
I'm having two models, the first one (model_1) accepts nested attributes for the second one (model_2). The second model has only one field (file), which is referenced in the form as file field.
The problem comes when no file has been selected. In this case — other than with say a text field — the field doesn't appear at all in the POST parameters which has the first model believe that no nested model should be created at all. Which fails to trigger validations etc.. If I were to add a second field to model_2 and the corresponding form and if I'm using a text input, everything will go through just fine and naturally validations work fine as well for the file field.
Anyone have experience on how to go about this?
And for better some (simplified) code — the form:
= form_for #model_1, :html => { :multipart => true } do |f|
- # fields for model 1 …
= f.fields_for :model_2 do |builder|
- # if this is empty, it's like no model_2 would be created at all:
= builder.file_field :file
Model 1:
class Model1 < ActiveRecord::Base
has_many :model_2s, :dependent => :destroy
accepts_nested_attributes_for :model_2s
# …
end
and Model 2:
class Model2 < ActiveRecord::Base
belongs_to :model_1
validates_presence:of :file
# …
end
I would suggest adding a check in your controller and returning a flash[:error] message if the file field is missing.
You could also manually add the fields if they don't exist, so that validation is triggered:
m1params = params[:model_1]
m1params[:model_2_attributes] = {} unless m1params.has_key?(:model_2_attributes)
Finally, you could create a fake attribue in your model_2 Model that you could use to ensure the model_2_attributes get's passed in the form:
class Model2
attr_writer :fake
def fake
#fake ||= 'default'
end
end
= form_for #model_1, :html => { :multipart => true } do |f|
- # fields for model 1 …
= f.fields_for :model_2 do |builder|
= builder.hidden_field :fake
= builder.file_field :file
At last, this seems to answer:
https://github.com/perfectline/validates_existence
Here is a sample:
class Unicorn < ActiveRecord::Base
belongs_to :wizard
belongs_to :person, :polymorphic => true
validates :wizard, :existence => true
validates :wizard_id, :existence => true # works both way
validates :person, :existence => { :allow_nil => true, :both => false }
end