Create a drop down menu using a Table Attribute in Rails Active Admin - ruby-on-rails

I need to create a dropdown field(membership_code), whose values are contained on a different table called members.
Schema
prereg
id
membership_code(string) not a foreign key
verification_code
members
id
membership_code
Prereg Active Admin Model
ActiveAdmin.register Prereg do
form do |f|
f.inputs "Preregistered Users" do
f.input :verification_code
f.input :email
#THIS LINE NEEDS TO BE CHANGED TO LIST DOWN THE MEMBERSHIP_CODE FROM MEMBERS
# f.input :membership_code, :as => :select, :collection => Members.all()
end
f.actions
end
To add, I was planning to have this logic wherein whenever you create a Prereg record, the selected "membership_code" would be deleted from the members.membership_code list.
How is this done in ActiveAdmin? Sorry I haven't found any good resource for DB Hooks and I'm still new to Rails.

I think you are looking for something as follows:
f.input :membership_code, as: :select, collection: Member.all.map(&:membership_code)

try this
f.input :membership_code, :as => :select, :collection => Members.select(:membership_code)
Thanks

Related

Wrong display of user names in ActiveAdmin forms

I created a FreeMeal tab in my DB; this tab has a foreign key on the User tab. When I use the form in Active Admin to create a new entry of FreeMeal, I get a list of all my users for the user input; but users aren't displayed the right way, like so:
edit: the form is automatically populated as I have the foreign key on users. I simply have the following code for this form in app/admin/free_meals.rb:
ActiveAdmin.register FreeMeal do
form do |f|
f.inputs "FreeMeal" do
f.input :user
f.input :reason
end
f.actions
end
end
I would like to have this list with my users' id, first_name and last_name.
How can I do that ?
Try this:
f.input :user, as: :select, collection: User.all.map{ |u| ["#{u.id}, #{u.first_name} #{u.last_name}", u.id]}, multiple: false

ROR HABTM implementation with simple forms

I am trying to implement HABTM model with two of my database tables. Two tables are Users and Ratings. According to general structure I should have following things
Users Model/Table
Ratings Model/Table
User_ratings Table
But User_ratings will have an extra column other than two ids and that will be a pre-defined string named stage. Stage will have pre-defined values such as appointment, completion e.t.c.
My first question is does this change the role of my middle table (through table) or will we still create just a migration for middle table.
Secondly, I am trying to implement a simple form to assign different users different ratings and my code looks like.
= simple_form_for #appointment, :html => {:class => 'form-horizontal'} do |f|
= f.input :start_datetime, as: :datetime_picker, input_html: {class: "datetime form-control"}
= f.input :end_datetime, as: :datetime_picker, input_html: {class:"datetime form-control"}
/ Now here I want three fields belonging to my middle table. Something like
= r.input :contact_id, :collection => Contact.all, :label_method => :get_contacts
= r.inout :rating_id, :collection => Rating.all, :label_method => :get_ratings
= r.hidden_field :stage, value: 'Appointment'
The problem here is that I don't have a model for middle table and hence I am stuck with how to do it with simple_form
Any kind of help will be highly appreciated. Thanks

Manipulating tags with acts_as_taggable_on and ActiveAdmin

I have a Post model which I'm accessing through ActiveAdmin. It's also taggable using the acts_as_taggable_on gem. So the admin can add, edit or delete tags from a specific Post.
The normal way to add the tagging functionality for the resource in your admin panel is by doing this in admin/posts.rb:
ActiveAdmin.register Post do
form do |f|
f.inputs "Details", :multipart => true do
f.input :tag_list
# and the other irrelevant fields goes here
end
f.buttons
end
end
However, I want to have the tags selected from a multiple select form field and not being entered manually in a text field (like it is with the code above). So I've tried doing this:
f.input :tag_list, :as => :select,
:multiple => :true,
:collection => ActsAsTaggableOn::Tag.all
but it doesn't work as expected. This actually creates new tags with some integer values for names and assigns them to that Post. Someone told me that extra code is needed for this to work.
Any clues on how this is done? Here's my model just in case: http://pastie.org/3911123
Thanks in advance.
Instead of
:collection => ActsAsTaggableOn::Tag.all
try
:collection => ActsAsTaggableOn::Tag.pluck(:name)
Setting the collection to Tag.all is going to tag your posts with the tag's ID, since that's how tags are identified by default (that's where the integer values for names are coming from). map(&:name) tells the form builder to use the tag's name instead.

Active Admin - refresh second drop down based on first drop down, Ruby on Rails

I am using Active Admin Gem on Ruby on Rails. I have a form in which i have selected category and sub category and then accordingly i have to fill the data. So i created two tables in sqlite added in active admin resouce.
Every thing is working fine but the drop down of sub category is not getting filtered based on the category choosen.
I am new to Ruby and RoR too. I don't know how to refresh dropdown of the subcategory after selecting category.
I know i can do it from AJAX and javascript but i dont know where to code for that?
Also, is there any specific filter avaliable in Active Admin which will make it happen without ajax or javascript.
Any ideas or help will be highly appreciated.
i don't know if there is any specific filter avaliable in Active Admin, but i solved it in this 3-steps way (assuming category - is a house, subcategory - is a flat):
1-st step: define helper containing ajax request
(of course, you have to predefine path in routes.rb)
#application_helper.rb
def remote_request(type, path, params={}, target_tag_id)
"$.#{type}('#{path}',
{#{params.collect { |p| "#{p[0]}: #{p[1]}" }.join(", ")}},
function(data) {$('##{target_tag_id}').html(data);}
);"
end
2-nd step: add this method for :onchange action
#admin/inhabitants.rb (DSL with formtastic)
form do |f|
f.inputs do
#...
f.input :house, :input_html => {
:onchange => remote_request(:post, :change_flats, {:house_id=>"$('#house_id').val()"}, :flat_id)
}
f.input :flat
#...
end
end
3-rd step: render result of filtering
(you can render partial instead of :text, I decided leave it in one activeadmin resource file )
controller do
def change_flats
#flats = House.find_by_id(params[:house_id]).try(:flats)
render :text=>view_context.options_from_collection_for_select(#flats, :id, :flat_number)
end
end
I accomplished this as any non-rails developer working on a rails project would - quick and dirty. Here's how:
#...
f.input :user, :input_html => {
:onchange => "
var user = $(this).val();
$('#order_location_id').val(0).find('option').each(function(){
var $option = $(this),
isCorrectUser = ($option.attr('data-user') === user);
$option.prop('disabled',!isCorrectUser);
});
"
}
f.input :location, collection: Location.all.map{ |loc|
[loc.name,loc.id, {"data-user" => loc.user_id}]
}
#...
No AJAX required. Note that this does not remove the unwanted options, it just disables them (sufficient for my scenario). This could easily be made modular with a helper, but I really only needed the functionality once.
For anyone else wrestling with the same problem, look at this railscast
I faced the same problem here
here's how I implemented multiple dynamic select menus in activeadmin:
config/initializers/active_admin.rb
config.register_javascript 'exam_registrations.js.coffee'
app/admin/exam_registrations.rb
form do |f|
f.inputs "Exam Registration Details" do
f.input :user_id, :label => 'Teacher', :as => :select, :collection => User.where(:admin => 'false', :active => true).order(:name), :include_blank => true
f.input :student_id, :hint => 'Students grouped by teacher names', :as => :select, :collection => option_groups_from_collection_for_select(User.where(:admin => false, :active => true).order(:name), :students, :name, :id, :name)
f.input :lesson_id, :hint => 'Lessons grouped by student names', :as => :select, :collection => option_groups_from_collection_for_select(Student.where(:active => true).order(:name), :lessons, :name, :id, :name)
end
f.buttons
end
app/assets/javascripts/exam_registrations.js.coffee
#first menu
jQuery ->
$('#exam_registration_student_id').parent().hide()
students = $('#exam_registration_student_id').html()
$('#exam_registration_user_id').change ->
user = $('#exam_registration_user_id :selected').text()
escaped_user = user.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/#])/g, '\\$1')
options = $(students).filter("optgroup[label='#{escaped_user}']").html()
if options
$('#exam_registration_student_id').html(options)
$('#exam_registration_student_id').parent().show()
else
$('#exam_registration_student_id').empty()
$('#exam_registration_lesson_id').empty()
# second menu
$('#exam_registration_lesson_id').parent().hide()
lessons = $('#exam_registration_lesson_id').html()
$('#exam_registration_student_id').click ->
student = $('#exam_registration_student_id :selected').text()
escaped_student = student.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/#])/g, '\\$1')
options = $(lessons).filter("optgroup[label='#{escaped_student}']").html()
if options
$('#exam_registration_lesson_id').html(options)
$('#exam_registration_lesson_id').parent().show()
else
$('#exam_registration_lesson_id').empty()
restart the server and the menus work!
Now it's possible with this gem https://github.com/holyketzer/activeadmin-ajax_filter, use in you form code like this:
f.input :category_id, as: :select # ...
f.input :subcategory_id, as: :ajax_select, data: {
ajax_search_fields: [:category_id],
search_fields: [:subcategory_atrribute],
url: '/admin/subcategories/filter'
}
And in you subcategory resource page:
ActiveAdmin.register Subcategory do
include ActiveAdmin::AjaxFilter
# ...
end
don't forget to include assets
You can also use activeadmin_addons gem Nested Select
dependent-select could be also a good option

Deleting a Paperclip Attachment in Activeadmin

I'm using paperclip to add image attachments to several models and Activeadmin to provide a simple admin interface.
I have this code in my activeadmin model file which allows for image uploads:
form :html => { :enctype => "multipart/form-data"} do |f|
f.inputs "Details" do
f.input :name
f.input :subdomain
end
f.inputs "General Customisation" do
f.input :standalone_background, :hint => (("current image:<br/>").html_safe + f.template.image_tag(f.object.standalone_background.url(:thumb))).html_safe, :as => :file
end
end
which works fine. All of the images I'm attaching like this are optional and so I'd like to give the user the option to remove a previously added image but can't work out how to do this in Activeadmin. All of the example I've seen are for situations where the attachments are managed through a separate has_many association rather than being part of the main model.
Does anyone know of a way to do this?
In your active admin view
form :html => { :enctype => "multipart/form-data"} do |f|
f.inputs "Details" do
f.input :name
f.input :subdomain
end
f.inputs "General Customisation" do
f.input :standalone_background, :hint => (("current image:<br/>").html_safe + f.template.image_tag(f.object.standalone_background.url(:thumb))).html_safe, :as => :file
f.input :remove_standalone_background, as: :boolean, required: false, label: "remove standalone background"
end
end
In your model
You could define a status flag like bellow
attr_writer :remove_standalone_background
def remove_standalone_background
#remove_standalone_background || false
end
OR (depreciated in rails 3.2)
attr_accessor_with_default : standalone_background,false
before_save :before_save_callback
And
def before_save_callback
if self.remove_standalone_background
self.remove_standalone_background=nil
end
end
You could implement this by creating a custom method. This can be done
member_action :custom_action, :method => :get do
//code
end
Also you should add a custom column with a link such as
index do
column "Custom" do |item|
link_to "Custom action", "/admin/items/custom_action"
end
end
Another option is to have a status flag for the attachment or image. Before saving the edited object, you unlink the image.
Thank you for your help guys. This is the final working code...
admin/product.rb
f.input :image, required: false, hint: (("Current image:<br/>").html_safe + f.template.image_tag(f.object.image.url(:thumb))).html_safe
f.input :remove_image, as: :boolean, required: false, label: "Remove Image"
models/product.rb
attr_writer :remove_image
def remove_image
#remove_image || false
end
before_validation { self.image.clear if self.remove_image == '1' }
Although accepts_nested_attributes_for(:foo, allow_destroy: true) only works with ActiveRecord associations like belongs_to we can borrow from its design to have paperclip attachment deletion work in a similar way.
(To understand how nested attributes work in Rails see http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html).
Add a <attachment_name>_attributes= writer method like below to your model that already uses has_attached_file:
has_attached_file :standalone_background
def standalone_background_attributes=(attributes)
# Marks the attachment for destruction on next save,
# if the attributes hash contains a _destroy flag
# and a new file was not uploaded at the same time:
if has_destroy_flag?(attributes) && !standalone_background.dirty?
standalone_background.clear
end
end
The <attachment_name>_attributes= method calls Paperclip::Attachment#clear to mark the attachment for destruction when the model is next saved.
Next open the existing app/admin/your_model_here.rb file (use the correct file path for your app) and setup strong parameters to permit the _destroy flag nested attribute on <attachment_name>_attributes:
ActiveAdmin.register YourModelHere do
permit_params :name, :subdomain,
:standalone_background,
standalone_background_attributes: [:_destroy]
In the same file, add a nested _destroy checkbox to the ActiveAdmin form block. This checkbox must be nested within <attachment_name>_attributes using semantic_fields_for (or one of the other nested attributes methods provided by formtastic).
form :html => { :enctype => "multipart/form-data"} do |f|
f.inputs "Details" do
...
end
f.inputs "General Customisation" do
...
if f.object.standalone_background.present?
f.semantic_fields_for :standalone_background_attributes do |fields|
fields.input :_destroy, as: :boolean, label: 'Delete?'
end
end
end
end
Your form should now show a delete checkbox when there is an attachment present. Checking this checkbox and submitting a valid form ought to delete the attachment.
Source: https://github.com/activeadmin/activeadmin/wiki/Deleting-Paperclip-Attachments-with-ActiveAdmin

Resources