I'm using Active Admin and I have a one-to-many relationship between two models:
class WeeklyMenu < ActiveRecord::Base
has_many :menu_items
attr_accessible :menu_items
accepts_nested_attributes_for :menu_items
end
In the admin page for WeeklyMenu I'd like to display five menu_items. This is what my admin page looks like at the moment:
ActiveAdmin.register WeeklyMenu do
form do |f|
f.inputs "Details" do
f.input :title
f.input :week
end
f.has_many :menu_items do |menu_item|
menu_item.input :title
end
f.buttons
end
end
That gives me a very nice interface for adding more menu_items, but I want the user to have five of them - no more, no less. How would I go about doing that?
Replace
f.has_many :menu_items do |menu_item|
menu_item.input :title
end
with
f.inputs "Menu items" do
5.times do
f.object.menu_items.build
end
f.fields_for :menu_items do |m|
m.inputs do
m.input :title
end
end
end
May not be the best solution, but this should work...
The fields_for answer that #user946611 suggested didn't work for me, but the following code did:
f.inputs 'Menu Items' do
(5 - f.object.menu_items.count).times do
f.object.menu_items.build
end
f.has_many :menu_items, new_record: false do |m|
m.input :title
m.input(:_destroy, as: :boolean, required: false, label: 'Remove') if m.object.persisted?
end
end
That will always show 5 forms for items, whether they have that many created or not. The new_record: false disables the "Add New Menu Item" button.
If you want to edit the form again, the answer of #user946611 lacks of a condition to tell whether the menu_item exists, because when submit and edit the form there will generate another five menu_items.
so it should be:
f.inputs 'Menu Items' do
if !f.object.menu_items.present?
5.times do
f.object.menu_items.build
end
end
f.fields_for :menu_items do |m|
m.inputs do
m.input :title
end
end
end
Activeadmin defines callbacks that can be used for this sort of thing:
https://github.com/activeadmin/activeadmin/blob/master/lib/active_admin/resource_dsl.rb#L157-L161
The after_build hook seems like an appropriate place to initialize a has_many relationship
ActiveAdmin.register WeeklyMenu do
after_build do |weekly_menu|
(5 - weekly_menu.menu_items.size).times do
weekly_menu.menu_items.build
end
end
form do |f|
f.inputs "Details" do
f.input :title
f.input :week
end
f.has_many :menu_items do |menu_item|
menu_item.input :title
end
f.buttons
end
end
Related
I have parent has many children relation. I want to easily manage children of specific parent.
I am trying like this:
form do |f|
f.inputs "Parent" do
f.input :name
end
f.inputs 'Children' do
f.has_many :children, new_record: true do |c|
c.input :name
end
end
f.actions
end
But I am getting:
undefined method `new_record?' for nil:NilClass
I have Rails 5. Is there a better way to make this work? What is the best way to allow user to manage child objects?
f.has_many :children do |c|
c.inputs "Children" do
c.input :name
#repeat as necessary for all fields
end
end
Make sure to have this in your parent model:
accepts_nested_attributes_for :children
user.rb
class User < ActiveRecord::Base
has_and_belongs_to_many :user_groups
end
Similarly, user_group.rb
class UserGroup < ActiveRecord::Base
has_and_belongs_to_many :users
end
Now the active admin page for user groups is as shown below:
ActiveAdmin.register UserGroup, as: 'UserGroup' do
form do |f|
f.inputs do
f.has_many :usergroup_users, as: 'member user' do |user|
user.input :user_id
end
end
end
end
Now this will create the user group form with fields for adding users to the new group. The button for adding new user to the group will be Add new User Group User. I want to modify this button label to something else. How can it be implemented?
Part of my problem is solved when using:
f.has_many :usergroup_users, heading: 'Add User to Group', as: 'member user' do |user|
...
end
This will change the header part to the required text. But the button label is still be a problem.
f.has_many :usergroup_users, new_record: 'Add member user' do |user|
...
end
The new_record attribute can be used to customize the button label.
In this way, one can change the text on new and edit pages buttons.
form do |f|
f.inputs do
f.input :email
f.input :phone
end
f.actions do
if resource.persisted?
# edit
f.action :submit, as: :button, label: 'Update Model'
else
# new
f.action :submit, as: :button, label: 'Create Model'
end
f.action :cancel, as: :link, label: 'Cancel'
end
end
I'm still a beginner with rails but have you tried this?
user.input :user_id, :input_html => { :value => 'your text' }
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.
This is similar to my previous question Ruby On Rails Active Admin has_many changing dropdown to use a different column
I figured out how to reassign a f.inputs but how would i go about reassigning the display of the data when viewing an item...
e.g:
Public Git Repo: https://github.com/gorelative/TestApp
Snippet of code i have in my fillups.rb
ActiveAdmin.register Fillup do
form do |f|
f.inputs do
f.input :car, :collection => Car.all.map{ |car| [car.description, car.id] }
f.input :comment
f.input :cost
f.input :mileage
f.input :gallons
f.buttons
end
end
end
Modify the show action
ActiveAdmin.register Fillup do
# ... other stuff
show do
attributes_table do
# add your other rows
row :id
row :car do |fillup|
link_to fillup.car.description, admin_car_path(fillup.car)
end
end
end
end
I have a infrastructure object composed for many datacenters. In the apps/admin/infrastructures.rb I have the following code:
form do |f|
f.inputs "Infrastructure details" do
f.input :name
f.has_many :datacenters do |datacenter_form|
datacenter_form.input :name
end
end
f.buttons
end
I can add datacenters with no problems but I don't know how I can delete it from infrastructure form.
Sep 2017 Update:
Rails 5.1.4, ActiveAdmin 1.0.0
Append :id and _destroy in permit_params along with other attributes from the model e.g. :name in your case. Then provide the :allow_destroy option in f.has_many too. Other requirements remain the same; like adding allow_destroy: true in accepts_nested_attributes_for.
Final look:
ActiveAdmin.register Infrastructure do
permit_params :name, datacenters_attributes: [:id, :_destroy, :name]
form do |f|
f.inputs "Infrastructure details" do
f.input :name
f.has_many :datacenters, heading: false,
allow_destroy: true,
new_record: false do |datacenter_form|
datacenter_form.input :name
end
end
f.buttons
end
end
ActiveAdmin Reference
This worked for me:
i.input :_destroy, as: :boolean
and in the Model remember to add :allow_destroy :
accepts_nested_attributes_for :images, allow_destroy: true
Solved adding the following line:
datacenter_form.input :_destroy, :as => :boolean, :required => false, :label => 'Remove'
The code looks like:
form do |f|
f.inputs "Infrastructure details" do
f.input :name
f.has_many :datacenters do |datacenter_form|
datacenter_form.input :name
datacenter_form.input :_destroy, :as => :boolean, :required => false, :label => 'Remove'
end
end
f.buttons
end
If you cant destroy the object nested. You need to put :_destroy in your app/admin/object.rb permit_params
permit_params :id,:name, :cod, :_destroy
I hope this will be helpful (I've changed my code to suit your example, so I hope there are no typos here):
form do |f|
f.inputs "Infrastructure details" do
f.input :name
f.has_many :datacenters do |datacenter_form|
datacenter_form.inputs :datacenters do
datacenter_form.input :name
end
datacenter_form.buttons do
link_to "Delete", admin_datacenter_path(datacenter_form.object), method: "delete", class: "button" unless datacenter_form.object.new_record?
end
end
end
f.buttons
end
and the controller method should be defined in datacenters.rb
controller do
def destroy
#datacenter = Datacenter.find(params[:id])
#datacenter.destroy
redirect_to edit_admin_retailer_path(#datacenter.infrastructure)
end
end
This should work:
datacenter_form.label :_delete
datacenter_form.check_box :_delete
This adds a checkbox for each nested object which will delete the object if checked.
Don't forget to add the following to your parent model
has_many :child_name, :dependent => :destroy