ActiveAdmin won't save has many and belongs to many field - activeadmin

I have 2 models. Category and Post. They are connected using a has_many_and_belongs_to_many relationship. I checked in the rails console and the relationship works.
I created checkboxes in activeadmin to set the post categories using this form field:
f.input :categories, as: :check_boxes, collection: Category.all
The problem is when I try to save it because every other field data (title, body, meta infos etc.) is saved, but the category stays the same even if I unchecked it, or checked another too.
I am using strong parameters like this:
post_params = params.require(:post).permit(:title,:body,:meta_keywords,:meta_description,:excerpt,:image,:categories)
Please give me some suggestions to make active admin save the categories too!
Best Wishes,
Matt

Try this in AA:
controller do
def permitted_params
params.permit post: [:title, :body, :meta_keywords, :meta_description, :excerpt, :image, category_ids: []]
end
end

Put something like this in /app/admin/post.rb:
ActiveAdmin.register Post do
permit_params :title, :body, :meta_keywords, :meta_description, :excerpt, :image, category_ids: [:id]
end
If you are using accepts_nested_attributes_for then it would look like this:
ActiveAdmin.register Post do
permit_params :title, :body, :meta_keywords, :meta_description, :excerpt, :image, categories_attributes: [:id]
end

I've tested, this might works for you and others as well
# This is to show you the form field section
form do |f|
f.inputs "Basic Information" do
f.input :categories, :multiple => true, as: :check_boxes, :collection => Category.all
end
f.actions
end
# This is the place to write the controller and you don't need to add any path in routes.rb
controller do
def update
post = Post.find(params[:id])
post.categories.delete_all
categories = params[:post][:category_ids]
categories.shift
categories.each do |category_id|
post.categories << Category.find(category_id.to_i)
end
redirect_to resource_path(post)
end
end
Remember to permit the attributes if you're using strong parameters as well (see zarazan answer above :D)
References taken from http://rails.hasbrains.org/questions/369

Related

Rails Admin filtering multiselect

I have a model with these associations:
has_many :ad_places, dependent: :destroy
has_many :places, through: :ad_places
And in my Rails Admin initializer:
edit do
field :places do
inline_add false
associated_collection_cache_all true
associated_collection_scope do
Proc.new do |scope|
scope = scope.order(:place_on_page)
end
end
end
field :html, :text
field :document
end
But my entries on the multiselect are not ordered by place_on_page, the request that does Rails Admin is ORER by places.id desc
It's basically the same configuration than this guy that's been fixed by this fix except that it doesn't work for me.
Do I miss something?
Check the logs on development to see what SQL is being generated, probably there's another ordering somewhere. to fix that try:
scope = scope.reorder(:place_on_page)

In ActiveAdmin Select from list of polymorphic items

So I have a list of items you can select multiple from and the list is of to different things (polymorphic) but I'm not sure how to implement this as what I have isn't working.
I've looked but I can't seem to find anything on this, only on how to filter polymorphic associations (not useful at this juncture).
Currently what I have:
f.input :items, multiple: true, as: :select, collection: Section.top_level.all + NavigationItem.all
I'd also like to add that I have found stuff on polymorphic nested form stuff but again, not relevent to what I'm asking for.
Did you try to use select2 for AA ?
form do |f|
f.inputs do
f.input :sections, as: :select2_multiple, :collection => NavigationItem.find_by_sql('select * from navigation_items'}).pluck(:name, :id)
end
f.actions
end
You can use find_by_sql to search through all polymorphic model across main table. Of course you will want to modify the query to use correct models and section levels.

ActiveAdmin not decorating show view

I am using ActiveAdmin on my Rails project. I use Draper as decorator but I don't understand why the show view is not decorated. According to the documentation it should be working just adding the decorate_with MyDecorator in my ActiveAdmin resource.
Here is my code:
ActiveAdmin.register Home do
...
decorate_with HomeDecorator
show do
attributes_table do # not being decorated
row :content
row :status
row :image
row :author_with_avatar
end
end
end
Does someone know what is wrong with my code ?
When I've run into this problem, it's because I've customized the controller's find_resource method. In that case be sure to return a manually decorated object:
def find_resource
MyModel.find_by_some_unique_finder(params[:id]).decorate
end
If all else fails you can force it using this approach:
show
attributes_table_for model.decorate do
row :decorator_method
row(:custom_label) { |m| m.decorator_method }
See http://activeadmin.info/docs/6-show-pages.html for more details

Rails 4.1 Nested Attributes and Fields For Getting Unpermitted Parameters and Not Saving

Research: Rails 4.0 beta, fields_for not accepting pluralized model_name in one-to-many association, Rails 4 Nested Attributes with fields_for Don't Save to Database
First, let's get the most common problem out of the way: incorrectly named attributes parameters for strong parameters. Mine is correctly plural.
class AdultsController < ApplicationController
...
def update
authorize #user
respond_to do |format|
if #user.update_attributes(user_params)
format.html { redirect_to unit_adult_path(#unit, #user), notice: "#{#user.full_name} was successfully updated." }
else
format.html { render action: 'edit' }
end
end
end
def user_params
params.require(:adult).permit(:first_name, :last_name, phones_attributes: [])
end
end
And my models are setup correctly
class User < ActiveRecord::Base
has_many :phones, dependent: :destroy
accepts_nested_attributes_for :phones, allow_destroy: true, reject_if: proc { |a| a["number"].blank? }
end
class Phone < ActiveRecord::Base
belongs_to :user, touch: true
end
And the view
# adult/_form.html.haml
= bootstrap_form_for [#unit, #user] do |f|
= f.text_field :first_name, control_col: 'col-md-4'
= f.text_field :last_name, control_col: 'col-md-4'
= f.fields_for :phones do |f_phone|
= f_phone.form_group do
= f_phone.select :kind, options_for_phones, hide_label: true, layout: :default
= f_phone.phone_field :number, hide_label: true, layout: :default
= f_phone.check_box :_destroy, label: 'remove'
But, when I submit the User form to save
Started PATCH "/units/2/adults/1" for 127.0.0.1 at 2014-07-11 15:20:17 -0700
Processing by AdultsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"pDjDVSiEs5qqHLqnbxQMeGWDOUGvhXPPvgyRGmitmps=", "adult"=>{"first_name"=>"Karl", "last_name"=>"Smith", "phones_attributes"=>{"0"=>{"kind"=>"other", "number"=>"888.1212", "_destroy"=>"0", "id"=>"173"}, "1"=>{"kind"=>"mobile", "number"=>"888.1212", "_destroy"=>"0", "id"=>"174"}} }, "commit"=>"Update Adult", "unit_id"=>"2", "id"=>"1"}
Unpermitted parameters: phones_attributes
I don't understand why the nested data is being rejected by the strong parameter evaluation. It looks correct to me.
The one thing I do notice is that the params data for "phones_attributes" value is a HASH not an ARRAY. In the user_params, phones_attributes: [] looks like it expecting an ARRAY. So I changed it to a HASH.
def user_params
params.require(:adult).permit(:first_name, :last_name, phones_attributes: {})
end
But now I get the following error.
Unpermitted parameters: 0, 1
So I tried specifying the field names in the "phones_attributes" array.
def user_params
params.require(:adult).permit(:first_name, :last_name, phones_attributes: [:id, :kind, :number])
end
And I still get.
Unpermitted parameters: phones_attributes
I know I must be missing something small, but I can't find my error.
EDIT: all my nested attributes forms do not work. Not 100% sure when they stopped, but ones that worked previously no longer work and have not been modified.
Figured this out. I was using javascript to copy the phone fields (kind, number) to make a new set of inputs available for entry. The script was adding non numeric characters to part of the field id, and this was causing rails to ignore all the submitted phone_attributes.
For the next person that comes along...
When fields_for renders out the fields, it will index each input name for uniqueness when the submitted post data is converted to params. In the example below, this number field
<input id="adult_phones_attributes_0_number" name="adult[phones_attributes][0][number]" type="tel" value="7773331111">
will look something like this when converted to params
"phones_attributes"=>{"0"=>{"number"=>"7773331111"}}
The hash key of "0" comes from the index created by fields_for. It's the "[0]" portion of the name.
In versions of rails past, if that nested attributes params hash key was not a number, the k/v pair was just ignored. Well now with strong parameters (I'm guessing the culprit), it will reject the entire "phones_attributes" hash.
My script was copying the input field, doing a regex on the html to change the "[0]" index to a random number. But sometimes it would replace it will non-digit characters. And this was causing the problem.

Make semantic_errors render the exact error-message

I have a model Camping which has_many Images. At least one image is required on Camping:
class Camping < ActiveRecord::Base
attr_accessible :images_attributes
has_many :images
validates_presence_of :images, :message => "At least one image is required"
accepts_nested_attributes_for :images, :allow_destroy => true
end
Then, in active_admin, which uses formtastic, I render the error message At least one image is required, with f.semantic_errors:
ActiveAdmin.register Camping do
form :html => { :multipart => true } do |f|
f.semantic_errors :images
#....
f.inputs "Images" do
f.has_many :images do |img|
#....
end
end
#....
end
end
This renders as:
Images At least one image is required.
How can I make it render: At least one image is required?
changing the f.semantic_errors :images into 'f.semantic_errors (removing :images) makes it render nothing; no error at all.
Note: The API documentation seems to imply that Formtastic always adds the :attribute name to the error; but I am not entirely sure how this code works.
If you want to use such custom messages you can add error messages that are related to the object’s state as a whole, instead of being related to a specific attribute
Change this
validates_presence_of :images, :message => "At least one image is required"
to something like
validate :should_have_images
def should_have_images
errors.add(:base, "At least one image is required") if images.blank?
end
If you want to use such custom messages you can add new method to Formtastic::Helpers::ErrorsHelper As follows
create new file at config/initializers/errors_helper.rb
Place following code to file
module Formtastic
module Helpers
module ErrorsHelper
def custom_errors(*args)
return nil if #object.errors.blank?
messages = #object.errors.messages.values.flatten.reject(&:blank?)
html_options = args.extract_options!
html_options[:class] ||= 'errors'
template.content_tag(:ul, html_options) do
messages.map do |message|
template.content_tag(:li, message)
end.join.html_safe
end
end
end
end
end
In activeadmin form use
f.custom_errors instead of f.semantic_errors *f.object.errors.keys

Resources