ActiveAdmin forms with has_many - belongs_to relationships? - ruby-on-rails

I have the models Home and Photo, which have a has_many - belongs_to relationship (a polymorphic relationship, but I dont think that matters in this case). I am now setting up active admin and I would like admins to be able to add photos to homes from the homes form.
The photos are managed by the CarrierWave gem, which I dont know if will make the problem easier or harder.
How can I include form fields for a different model in the Active Admin Home form? Any experience doing something like this?
class Home < ActiveRecord::Base
validates :name, :presence => true,
:length => { :maximum => 100 }
validates :description, :presence => true
has_many :photos, :as => :photographable
end
class Photo < ActiveRecord::Base
belongs_to :photographable, :polymorphic => true
mount_uploader :image, ImageUploader
end

Try something like this in app/admin/home.rb:
form do |f|
f.inputs "Details" do
f.name
end
f.has_many :photos do |photo|
photo.inputs "Photos" do
photo.input :field_name
#repeat as necessary for all fields
end
end
end
Make sure to have this in your home model:
accepts_nested_attributes_for :photos
I modified this from another stack overflow question: How to use ActiveAdmin on models using has_many through association?

You could try this:
form do |f|
f.semantic_errors # shows errors on :base
f.inputs # builds an input field for every attribute
f.inputs 'Photos' do
f.has_many :photos, new_record: false do |p|
p.input :field_name
# or maybe even
p.input :id, label: 'Photo Name', as: :select, collection: Photo.all
end
end
f.actions # adds the 'Submit' and 'Cancel' buttons
end
Also, you can look at https://github.com/activeadmin/activeadmin/blob/master/docs/5-forms.md (See Nested Resources)

I guess you are looking for a form for a nested model. Take a look at following railscasts.
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/197-nested-model-form-part-2
I cannot tell you much about active_admin, but I think this should not make a difference in handling the nested model.

I have a has_one model, like this:
f.has_many :addresses do |a|
a.inputs "Address" do
a.input :street ... etc.
While this correctly reflects our associations for Address (which is a polymorphic model) using f.has_one fails. So I changed over to has_many and all's well. Except now we have to prevent our users from creating multiple addresses for the same entity.

Related

Why I need to select image again after validation failed

I have two models
class ComfortFactorSubCategory < ApplicationRecord
has_one :image, as: :imageable, dependent: :destroy
validates :heading, presence: true
accepts_nested_attributes_for :image, :reject_if => lambda { |a| a[:name].blank? }, allow_destroy: true
end
class Image < ApplicationRecord
belongs_to :imageable, polymorphic: true
mount_uploader :name, IconUploader
end
and my admin/comfort_factor_sub_category.rb I have these lines
ActiveAdmin.register ComfortFactorSubCategory do
permit_params do
permitted = [:heading, image_attributes: [:name, :_destroy, :id], additional_instruction_ids: []]
permitted
end
form do |f|
f.inputs do
f.input :heading
f.input :additional_instructions, as: :select, collection: AdditionalInstruction.pluck(:description, :id)
f.fields_for :image do |b|
b.input :name, label: "Image", :as => :file
end
end
f.actions
end
end
when I submit the form with wrong information lets say without heading and validation fail why do I need to select the image again while I did select in first submission
Seems like you need f.hidden_filed :name_cache for caching uploaded file
Take a look at the CarrierWave making uploads work across form redisplays section and upload through accept_nested_attributes_for wiki article
This is constrained by browser for security reasons. It avoids pre-filling the form with the default file object's value when error page is rendered.
This is a detailed excerpt about this.
This however is usually not supported by browsers. The usual
explanation is “security reasons.” And indeed it would be a security
risk if files from the user’s disk were submitted without the user’s
content. It might be all too easy to lure some users into submitting
some password files!
I also found this another answer talking about the same problem with ASP.net framework.

Rails, Active admin, nested form, dynamic label value - issue with the form object

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'

ActiveAdmin Form not saving nested object

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

Editing many-to-many relations in Activeadmin

I am looking for a way to edit/add keywords related to an article, inline in Activeadmin.
I have defined a simple many-to-many setup:
class Area < ActiveRecord::Base
has_many :area_keywords
has_many :keywords, :through => :area_keywords
accepts_nested_attributes_for :keywords, :reject_if => :all_blank, :allow_destroy => true
end
class AreaKeyword < ActiveRecord::Base
belongs_to :area
belongs_to :keyword
end
class Keyword < ActiveRecord::Base
has_many :area_keywords
has_many :areas, :through => :area_keywords
end
I would like to add and edit the keywords in en Area form, so I setup this in Aciveadmin:
ActiveAdmin.register Area do
form do |f|
f.inputs "Area details" do
f.input :title
f.input :description
end
f.has_many :keywords do |k|
if k.object.nil?
k.input :word, :label => 'Keyword'
else
k.input :word, :label => k.object.word
k.input :_destroy, :as => :boolean, :label => "delete"
end
end
end
end
This works as expected.
But if I add the same Keyword to two different areas, the Keyword will just be created twice.
When entering a new keyword (in the Area form), I would like it to automatically create a relation to an existing keyword, or create a new keyword, if it does not exist. What would be the best way to go about it?
This is a pretty late answer :) but I actually have encountered kind of a similar issue in one of my projects...I had to add keywords/tags to two different models, but they could share them. At first I did just like you, and it was creating a record for each time you "attach" a keyword/tag to a model.
A better way to handle it is to use a tagging system. And I achieved a pretty neat system by combining two really good gems: 'acts-as-taggable-on' (https://github.com/mbleigh/acts-as-taggable-on) and 'select2-rails' (https://github.com/argerim/select2-rails)
In my own project, I actually did something similar to you and created a model just to have a list of all the appropriate keywords I wanted. But 'act-as-taggable-on' doesn't necesarilly requires a list of accepted keywords...so you can create them on the fly, and it will automatically handle duplicates, counts etc.
'select2-rails' just allows you to have an nice interface to add and remove keywords in one field, rather than using checkboxes, select options, or a text input where you would have to manually separate your string with commas or any separators.
If anyone need more details on how I implemented all, I would be more than glad to provide more code .. but the documentation for both of them are pretty straightforward!
EDIT: Well, I have a feeling some code would actually be useful :)
Bundle install both gem in your Gemfile
gem 'acts-as-taggable-on'
gem 'select2-rails'
In your Area model, you could add the following and do something like
class Area < ActiveRecord::Base
# .. your code
attr_accessible :area_keyword_list
acts_as_taggable_on :area_keywords
end
And in your ActiveAdmin file
ActiveAdmin.register Area do
form do |f|
f.inputs do
# .. whatever fields you have
f.input :area_keyword_list,
:as => :select,
:multiple => :true,
:collection => # here either a list of accepted keyword..or just left open,
:input_html => { :class => "multiple-select" }
end
end
end
and the JS for select2 is quite simple ...
$(".multiple-select").select2();
Voilà !

Nested form in active_admin with select or create option

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]

Resources