Activeadmin form with nested has_one inside has_many - ruby-on-rails

I am using ActiveAdmin on my Rails project.
I have several nested models like following:
A MapArticle model which has_many Locations (address, city, postcode, …) which has_one Marker (icon and color).
My problem is about the form action in ActiveAdmin. I can’t figured out how to display the has_one marker relation. Everything I tried didn’t seems to work.
MapArticle model:
class MapArticle < ActiveRecord::Base
belongs_to :post, polymorphic: true
has_many :locations, as: :locationable, dependent: :destroy
accepts_nested_attributes_for :locations, reject_if: :all_blank, allow_destroy: true
end
Location model:
class Location < ActiveRecord::Base
belongs_to :locationable, polymorphic: true
has_one :marker, as: :markable, dependent: :destroy
accepts_nested_attributes_for :marker, reject_if: :all_blank, allow_destroy: true
end
Marker model:
class Marker < ActiveRecord::Base
belongs_to :markable, polymorphic: true
end
The form:
f.inputs t('activerecord.models.map_article.one'), for: [:map_article, f.object.map_article || MapArticle.new] do |map_article|
map_article.input :online,
as: :boolean,
hint: I18n.t('form.hint.map_article.online')
map_article.has_many :locations, heading: false, allow_destroy: true, new_record: t('add.feminin', klass: t('activerecord.models.location.one')) do |location|
location.input :address
location.input :city
location.input :postcode
location.input :geocode_address,
hint: t('form.hint.location.geocode_address'),
input_html: { id: 'gmaps-input-address' }
location.input :latitude,
label: false,
input_html: { id: 'gmaps-output-latitude', class: 'hide' }
location.input :longitude,
label: false,
input_html: { id: 'gmaps-output-longitude', class: 'hide' }
# This doesn’t work
location.inputs t('activerecord.models.marker.one'), for: [:marker, location.object.marker || Marker.new] do |marker|
marker.input :color
marker.input :icon
end
end
end
Thanks for your help !
My Project:
Ruby 2.2.2
Rails 4.2.4
ActiveAdmin 1.0.0 pre1

Related

ActiveAdmin nested has_many

Consider the following models:
class User < ApplicationRecord
accepts_nested_attributes_for :memberships, allow_destroy: true
has_many :memberships, dependent: :destroy
has_many :accounts, through: :memberships
end
class Account < ApplicationRecord
accepts_nested_attributes_for :memberships, allow_destroy: true
accepts_nested_attributes_for :users, allow_destroy: true
has_many :memberships, dependent: :destroy
has_many :users, through: :memberships
end
class Membership < ApplicationRecord
belongs_to :account
belongs_to :user
before_validation { self.role = "admin" if role.blank? }
validates :role, presence: true
pg_enum :role, %i[admin support user]
end
In ActiveAdmin there is already a form in place to create an Account and a Membership from an existing User. That looks like this:
form do |f|
...
f.inputs do
f.has_many :memberships, heading: false, allow_destroy: true, new_record: "Add existing user" do |m|
m.input :user_id, as: :searchable_select, ajax: { resource: User }
m.input :role, as: :select, label: false, include_blank: false
end
end
...
What I'm trying to do is update the form to allow a way to create an Account and a new User with a Membership with a specific role. This is what I've tried so far (within the same form block as the one above):
f.inputs do
f.has_many :users, heading: false, allow_destroy: true, new_record: "Add new user" do |u|
u.input :name
u.input :email, as: :string
u.has_many :memberships, heading: false, allow_destroy: true, new_record: "Add membership" do |m|
m.input :role, as: :select, label: false, include_blank: false
end
end
end
The form produced:
This doesn't work. If I don't fill in a role for the User's membership this will "work" and the before_validation in the Membership model will assign the User a Membership with role Admin. However, if I try to add a role to the User through the form and click "Create Account", then I am returned to the form where I see an error stating that Account must exist. This leads me to believe that the form is ignoring the second has_many that I've nested under f.has_many :users.
I've also tried approaching this by creating an input in the f.has_many :users block:
u.input :memberships, as: :select, label: "Role", include_blank: false, collection: Membership.roles
Instead of telling me that the Account must exist, this ignores any value I assign for the role, creates the User and assigns it a Membership with the role of Admin
How can I make this happen?
When you add through the form this is performed using JavaScript that includes before and after creation hooks I don't have an example but look at the code and see if it helps.

Update a relation in activeadmin

I have two models.
fb_page.rb
has_one :fb_page_template, dependent: :destroy
accepts_nested_attributes_for :fb_page_template, :allow_destroy => false
fb_page_template.rb
belongs_to :fb_page
has_many :subscriptions
Active admin
ActiveAdmin.register FbPage do
form title: 'Facebook page form' do |f|
f.has_many :fb_page_template, new_record: false, allow_destroy: false do |k|
k.input :subscribed
end
end
end
Now when I try to update the form, it tries to delete subscriptions and fb_page_template as well.
All I want is to update the value of subscribed which is in fb_page_template
I think that you're missing couple things here:
You need to allow accepts_nested_attributes_for :subscriptions, :allow_destroy => false in your fb_page_template.rb
You need to allow all nested attributes in ActiveAdmin too.
You need to nest the forms.
This is what I have in my fb_pages.rb for ActiveAdmin:
ActiveAdmin.register FbPage do
permit_params :attribute_name_for_fb_page,
fb_page_template_attributes: [
:id, :fb_page_id, :attribute_name_for_fb_page_template,
subscriptions_attributes: [
:subscribed,
:fb_page_template_id
]
]
form title: "Facebook page form" do |f|
f.inputs do
f.input :attribute_name_for_fb_page
f.has_many :fb_page_template, allow_destroy: false do |t|
t.input :attribute_name_for_fb_page_template
t.has_many :subscriptions do |s|
s.input :subscribed, as: :boolean
end
end
end
f.actions
end
end
And this is what I have in the fb_page_template.rb
class FbPageTemplate < ApplicationRecord
belongs_to :fb_page
has_many :subscriptions
accepts_nested_attributes_for :subscriptions, :allow_destroy => false
end
Hope this works for you.

How to limit an association list based on a related model

I know that I should know this, but I cannot seem to figure it out at all and I'm still new to development...
So I have four models...
Appointments
class Appointment < ActiveRecord::Base
belongs_to :user
belongs_to :profile
belongs_to :location
end
Profiles
class Profile < ActiveRecord::Base
belongs_to :user
has_many :appointments
has_many :profile_locations
has_many :locations, through: :profile_locations
accepts_nested_attributes_for :profile_locations, reject_if: :all_blank, allow_destroy: true
accepts_nested_attributes_for :locations, reject_if: :all_blank, allow_destroy: true
end
profile_locations
class ProfileLocation < ActiveRecord::Base
belongs_to :profile
belongs_to :location
belongs_to :location_type
accepts_nested_attributes_for :location
end
and locations
class Location < ActiveRecord::Base
has_many :profile_locations
has_many :profiles, through: :profile_locations
has_many :appointments
end
On the create appointments page, I already have an associated profile on the record. I also have an association field on my simple_form for locations that I want to be able to assign to the appointment based on those tied to the profile..
I was trying something like this, but cannot seem to getting working.
%td= f.association :location, :as => :collection_select, collection: Location.where( location.profile_location.profile_id: #profile.id ), label_method: :address_1, value_method: :id, include_blank: false, :input_html => {:class => "input-small"}, :label => "Select The Location"
Am I missing something here or is there an easier way to query this? Any guidance on any of this would be helpful.
If you are are using simple_form you should be creating collection_input like this:
%td= f.input :location, collection: Location.joins(:profile_location).where(profile_locations: { profile_id: #profile.id })
Thanks ksarunas.... I needed a minor tweak, but got it running!
%td= f.association :location, :as => :collection_select, collection: Location.includes(:profile_locations).where(profile_locations: { profile_id: #appointment.profile_id })
Was getting an error trying to pull in the #profile.id and had to pluralize the profile_locationS in both places.

ActiveAdmin Form Multiple Nested HMT relationships with has_many

i'm new to ActiveAdmin and Rails and i struggle on something to build up my ActiveAdmin interface.
Consider the following models :
class PageType < ActiveRecord::Base
has_many :fields, class_name: 'PageField'
accepts_nested_attributes_for :fields, allow_destroy: true
end
class PageField < ActiveRecord::Base
belongs_to :page_type
has_many :page_has_fields
has_many :pages, through: :page_has_fields
accepts_nested_attributes_for :page_has_fields, allow_destroy: true
end
class PageHasField < ActiveRecord::Base
belongs_to :page
belongs_to :page_field
end
class Page < ActiveRecord::Base
belongs_to :page_type
has_many :page_has_fields, dependent: :delete_all
has_many :page_fields, through: :page_has_fields
accepts_nested_attributes_for :page_fields, allow_destroy: true
end
In Active Admin I want to create some page templates to handle "static" pages. And in each of the pages, I want to update the content of each fields related to the templates page.
Thus far, what I did worked with this code :
ActiveAdmin.register Page do
permit_params :name, :page_type_id, :page_id,
:page_fields_attributes => [:id, :name, :field_type, :page_id,
:page_has_fields_attributes => [:id, :content, :page_id]
]
form do |f|
f.inputs
f.has_many :page_fields, heading: false, new_record: false do |g|
g.inputs :name, :required
g.has_many :page_has_fields, new_record: false do |h|
h.input :content if h.object.page_id == f.object.id
end
end
f.actions
end
end
But the second has_many seems really wrong to me, and i'm sure there are a better solution to this problem.
If i don't go with the "if", inputs are created for the right fields, but for every single page.
Is there a way to specify an ID or a parameter in has_many ? Or a better tag to handle situation like this ?
Thanks
Try changing your setup to something more like this
ActiveAdmin.register Page do
...
form do |f|
f.inputs do
f.input :some_column
f.input :some_other_column
f.input :page_fields, as: :check_boxes, checked: PageField.all.map(&:name)
f.input :page_has_fields, as: :check_boxes, checked: PageField.all.map(&:content)
end
f.actions
end
end

Can't mass-assign protected attributes: works_attributes, educations_attributes in rails nested model

I am trying to save the model called applicant with nesting to work and education model. When saving the model, I am getting:
Can't mass-assign protected attributes: works_attributes, educations_attributes error.
I am also getting an error for an undefined method `klass' for nil:NilClass. I am using Rails 3.2.
My model code:
applicant.rb
class Applicant < ActiveRecord::Base
attr_accessible :first_name, :last_name, :location, :email, :mob_no, :alternative_no, :linkedin, :facebook, :twitter, :message, :resume, :job_id
has_many :works, :dependent => :destroy
has_many :educations, :dependent => :destroy
accepts_nested_attributes_for :works, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
accepts_nested_attributes_for :educations, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end
work.rb
class Work < ActiveRecord::Base
attr_accessible :applicant_id, :company_name, :description, :end_month, :end_year, :start_month, :start_year, :title
belongs_to :applicant
end
education.rb
class Education < ActiveRecord::Base
attr_accessible :applicant_id, :end_month, :end_year, :institution_name, :major, :start_month, :start_year, :title
belongs_to :applicant
end
Try including work and education attributes like this ..
class Applicant < ActiveRecord::Base
attr_accessible :works_attributes, educations_attributes

Resources