Sortable for has_many does not sort properly - activeadmin

I have an association of experiences on resume, and create the fields like this:
models/resume.rb
has_many :experiences, -> { order(position: :asc) }
models/experience.rb
belongs_to :resume
acts_as_list scope: :resume
Admin page:
admin/user.rb
inputs "Experience" do
f.semantic_fields_for :resume do |r|
r.has_many :experiences, sortable: :position, allow_destroy: true do |a|
a.input :title
end
end
end
When i save the form, the records are not saved in the correct order, nor the reverse of the correct order. On each save, where there are 3 records in my test, the 1st record goes the the bottom, the middle record goes to the top and the last record goes to the middle.

acts_as_list is 1 based, activeadmin defaults to 0 based lists. adding sortable_start: 1 fixes the issue:
inputs "Experience" do
f.semantic_fields_for :resume do |r|
r.has_many :educations, sortable: :position, sortable_start: 1, allow_destroy: true do |a|
a.input :title
end
end
end

Related

jQuery, activeadmin: custom filter with ransack. how to alter displayed text in search box

i got activeadmin (1.0.0.pre1) working with rails-jquery-autocomplete (1.0.2) [rails-4 setup].
i am able to auto-complete queries and call a search on them; however, when the search returns and the index form reloads, the search box (in sidebar panel) displays queried string wrapped in ["string"] (square braces and quotes)
e.g. if i search with AWonderfulDay and select an auto-completed element, the form reload results in ["AWonderfulDay"] shown as innerText of input element (search box)
Following is the generated UI element
<input data-autocomplete="/comments/autocomplete_comments" id="q_comments_in" name="q[comments_in]" type="text" value="["SearchString"]" class="ui-autocomplete-input" autocomplete="off">
The search has been implemented using ransack and the filter is:
filter :comments_in, as: :autocomplete, url: '/comments/autocomplete_comments',
label: 'Search Comments', required: false,
wrapper_html: {style: "list-style: none"}
pointed to a trivial:
ransacker :comment,
:formatter => ->(comment) {
data = User.joins(:profile => :comment).where("comments.comment = ?", comment).map(&:id)
data = data.present? ? data: nil
} do |parent|
parent.table[:id]
end
i do know this is because of in predicate (doesn't happen with cont predicate and i have that in another filter working well, e.g. filter :comments_cont will not cause this)
edit 1:
Also, https://github.com/activerecord-hackery/ransack/issues/345 shows a snapshot with same behavior.
This also led me to another question here Custom search with ransacker
i should have done a better job at looking up for them earlier. sorry for that!
edit 2:
here are my model relations:
class User < ActiveRecord::Base
belongs_to :profile, :inverse_of => :users, :touch => true
class Profile < ActiveRecord::Base
has_one :comment, dependent: :destroy
class Comment < ActiveRecord::Base
belongs_to :profile, touch: true
i solved it by correcting my use of ransack.
In models/comment.rb:
scope :search_comment, lambda { |x| ..}
def self.ransackable_scopes(auth_object = nil)
[:search_comment]
end
In admin/profile.rb
filter :search_comment, as: :autocomplete, url: "controller_url",
label: 'Search Comment', required: false,
wrapper_html: {style: 'list-style: none'}

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 column of associated resource in index table non-linked

Okay, using ActiveAdmin (0.6.3) and am able to use the following code to get a caller's location attribute to appear in the table of callers. The name of each location appears as a link to the "show" action for the location. The "show" action and result is not useful for my application. I want to remove the link but keep the text. Help? Thanks :)
ActiveAdmin.register Caller do
index do
column 'Location', :location, :sortable => 'locations.name'
end
controller do
def scoped_collection
resource_class.includes(:location)
end
end
end
class Caller < ActiveRecord::Base
attr_accessible :active, :assignedname, :callingnumber, :description, :location_id, :lookupcount, :lastlookuptime
belongs_to :location
end
class Location < ActiveRecord::Base
attr_accessible :active, :description, :name, :callers_attributes
has_many :callers, dependent: :destroy
end
Try this.
index do
column 'Location', :sortable => 'locations.name' do |caller|
caller.location.name
end
end

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

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

rails_admin searchable association

I am using rails_admin together with globalize3 and cannot get searchable associations to work. Here are the models (Person has_one/belongs_to Name has_many/belongs_to NameTranslation):
class Person < ActiveRecord::Base
has_one :name, inverse_of: :person
end
class Name < ActiveRecord::Base
belongs_to :person, inverse_of: :name
translates :first_name, :last_name
has_many :name_translations, inverse_of: :name, dependent: :destroy
end
class NameTranslation < ActiveRecord::Base
belongs_to :name, inverse_of: :name_translations
end
The NameTranslation model is coming from globalize3, it contains the same attributes as name (first_name and last_name) plus locale and name_id,.
In config/initializers/rails_admin.rb I have
config.model Person do
list do
field :name do
searchable name_translations: :last_name
end
end
end
Then, in the GUI, when I add a filter on name, I get:
SQLite3::SQLException: no such column: name_translations.last_name: SELECT "people".* FROM "people" WHERE (((name_translations.last_name LIKE '%freud%'))) ORDER BY people.id desc LIMIT 20 OFFSET 0
Obviously, rails_admin is looking for a column named name_translations.last_name in people instead of joining/including names and name_translations - why?
What I need rails_admin to do is this, working in irb:
>> Person.joins( name: :name_translations ).where('name_translations.last_name like "test"')
which generates the following SQL:
SELECT "people".* FROM "people" INNER JOIN "names" ON "names"."person_id" = "people"."id" INNER JOIN "name_translations" ON "name_translations"."name_id" = "names"."id" WHERE (name_translations.last_name like "test")
Can this be done in rails_admin? Thanks for your help...
From this thread, I followed Nick Roosevelt's suggestion and it worked for my case
class Room < ActiveRecord:Base
has_many :time_slots
end
class TimeSlot < ActiveRecord::Base
belongs_to :room
rails_admin do
list do
field :day do
searchable true
end
# field :room do
# searchable room: :name
# end
field :room do
searchable [{Room => :name}]
queryable true
end
end
end
end
I tried searchable room: :name and it was not working, but searchable [{Room => :name}] seem to make it work.
I had a similar problem with a has one relationship.
The way I solved it was to set a default_scope on the model and join it with the associated table (it is was the only way I could get rails admin to join these two tables).
I also had to set queryable true on the associated field.
Imagine that you had to search only inside the name association, then here's how it would work:
class Person < ActiveRecord::Base
has_one :name, inverse_of: :person
default_scope { eager_load(:name) }
end
config.model Person do
list do
field :name do
queryable true
searchable [:column1, :column2, ..]
end
end
end
However, you need to search through the has many association and I don't know whether that approach would still work, but here's a guess:
class Person < ActiveRecord::Base
has_one :name, inverse_of: :person
has_many :name_translations, through: :name
default_scope { eager_load(:name_translations) }
end
config.model Person do
list do
field :name_translations do
queryable true
searchable :last_name
end
end
end

Resources