f.has_many :offers,heading: 'Offers' do |item|
item.input :quantity
item.input :offer_type_id, :prompt => 'Select Offer Type', :as => :select, :collection => OfferType.all.map{|m| [m.title, m.id]}
item.input :_destroy, :as => :boolean
end
It works fine and has_many association created. I want that the button for adding associated data automatically clicked or open when I load page.
Add new Offer
Instead that user click on it for first associated data it automatically clicked
In AA controller block you need yo build offer - it will add the offer's fields to the form:
controller do
def new
super do
resource.offers.build
end
end
end
Related
Im using Rails 4 and I have a form within active admin that does not pre-populate or load relationship data into the edit form. If I dont define a form then the default that is loaded by active admin does, but it is shows the object and not the object.name for example so I have set out to edit it.
Here is what I have
form do |c|
c.semantic_errors *c.object.errors.keys
c.inputs "Event" do
c.input :title
c.input :date, :as => :datetime_picker, :local => true
c.input :description
end
c.inputs "Training Request" do
c.inputs :for => [:training_request, c.object.training_request || c.object.build_training_request] do |w|
list_of_training_requests = TrainingRequest.fulfilled.collect {|t| t.host.name }
w.input :id, as: :select, :collection => list_of_training_requests
end
end
c.inputs "Trainer" do
c.inputs :for => [:trainer, c.object.trainer || c.object.build_trainer] do |x|
list_of_trainers = Trainer.qualified.collect {|t| t.name }
x.input :id, as: :select, :collection => list_of_trainers
end
end
c.actions
end
The form loads without any errors and does list data just not what is set the in the database e.g.
If anyone can point me in the right direction it would be very much appreciated.
If the only problem with the original forms is that it just displays the object instead of name you could overwrite to_s in your models. For example:
class Trainer < ActiveRecord::Base
def to_s
name
end
end
Then when you call an instance of Trainer it should display the name property.
I need to create a form in my rails3 application that, when saved, will validate the fields and then submit them. I need a row for each field essentially.
The reason for this is that each 'user' has multiple attributes. For example:
User-Password
Expiration
Access-Group
Have tried a nested form but that doesn't really work for me.
In my console, this works pretty well for me:
user = Array.new
user << {:username => "jenny", :attribute_name => "User-Password", :value => "123"}
user << {:username => "jenny", :attribute_name => "Expiration", :value => "123"}
user << {:username => "jenny", :attribute_name => "Access-Group", :value => "123"}
User.create(user)
That inserts a number of rows, each with the same username but different attribute names and values. Perfect.
My problem is, how do I do this using a single form?? Initially I had a parent model and a nested form but I can't figure it out.
This should actually be pretty straightforward nested form. Let us assume
class User
has_many :attributes
accepts_nested_attributes_for :attributes, :reject_if => :all_blank, :allow_destroy => true
end
class Attribute
belongs_to :user
end
and an Attribute has an attribute_name, a value and a user_id.
Then your form, using haml, simple_form and cocoon would look like
= simple_form_for #user do
= f.input :name
#attributes
= f.simple_fields_for :attributes do |attribute|
= render 'attribute_fields', :f => attribute
.links
= link_to_add_association 'add new attribute', f, :attributes
and you add a partial called _attribute_fields.html.haml
.nested-fields
= f.input :attribute_name
= f.input :value
= link_to_remove_association "remove attribute", f
If the attributes are fixed, you could easily change the input for attribute_name to
= f.input :attribute_name, :as => :select, :collection => {'User-Password', 'Expiration', 'Access-Group' }
If you want to read more about different types of nested forms, I have written a blogpost about it in greater detail.
[EDIT] Adding server-side validation to Attribute model:
Inside class Attribute you need to add:
validate :check_valid_values
def check_valid_values
if attribute_name == 'Expiration'
errors.add(:value, "Must be a valid date for Expiration") unless value.is_a_valid_date?
end
end
Note that the method is_a_valid_date? does not exist, this is just to provide a small example. In this validation method you would then add all the possible attribute-value combinations with their validation.
Hope this helps.
I am using ActiveAdmin gem in my project.
I have 2 models using has_many through association. The database schema looks exactly the same as the example in RailsGuide. http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association
(source: rubyonrails.org)
How can I use ActiveAdmin to ...
show appointment date of each patient in physicians page?
edit appointment date of each patient in physicians page?
Thanks all. :)
For 1)
show do
panel "Patients" do
table_for physician.appointments do
column "name" do |appointment|
appointment.patient.name
end
column :appointment_date
end
end
end
For 2)
form do |f|
f.inputs "Details" do # physician's fields
f.input :name
end
f.has_many :appointments do |app_f|
app_f.inputs "Appointments" do
if !app_f.object.nil?
# show the destroy checkbox only if it is an existing appointment
# else, there's already dynamic JS to add / remove new appointments
app_f.input :_destroy, :as => :boolean, :label => "Destroy?"
end
app_f.input :patient # it should automatically generate a drop-down select to choose from your existing patients
app_f.input :appointment_date
end
end
end
In answer tomblomfield follow up question in comments:
Try the following in your AA ActiveAdmin.register Model do block:
controller do
def scoped_collection
YourModel.includes(:add_your_includes_here)
end
end
This should lazy load all your associations for each index page in a separate query
HTH
It should solve the N+1 query problem.
show do
panel "Patients" do
patients = physician.patients.includes(:appointments)
table_for patients do
column :name
column :appointment_date { |patient| patient.appointments.first.appointment_date }
end
end
end
It's work for me (with chosen)
permit_params category_ids: []
form do |f|
inputs 'Shop' do
input :category_ids, collection: Category.all.collect {|x| [x.name, x.id]}, as: :select, multiple: true, input_html: { class: "chosen-input", style: "width: 700px;"}
end
f.actions
end
#monfresh #tomblomfield you can do
has_many :appointments, ->{ includes(:patients) }, :through => :patients
in the physicians model
...or, I'm not sure if you can use it with formtastic but you could make the scope optional with something like
has_many :appointments :through => :patients do
def with_patients
includes(:patients)
end
end
and appointment.patient wont n+1 anymore
If you would like show multiple field in a panel row you can use following view:
show do |phy|
panel "Details" do
attributes_table do
... # Other fields come here
row :appointment_dates do
apps=""
phy.appointments.all.each do |app|
apps += app.patient.name + ":" + app.appoinment_date + ", "
end
apps.chomp(", ")
end
end
end
end
To place it in you redit form first put appointment_ids to permitted list:
permit_params: appointment_ids:[]
Add has many relationship to the form
form do |f|
f.has_many :appointments do |app|
app.inputs "Appointments" do
app.input :patients, :as => :select, :label => "Assigned Patients"
app.input :appointment_date
end
end
end
Should work if there is no coding error.
Regarding #2, it should be like this:
form do |f|
f.inputs 'Physician Details' do
f.input :name
end
f.inputs 'Physician Appointments' do
f.has_many :appointments,
heading: false,
new_record: 'Add new appointment',
remove_record: 'Delete appointment',
allow_destroy: true do |app|
app.input :patient, label: 'Choose the patient', collection: Patient.pluck(:name, :id)
app.input :appointment_date
end
end
Regarding the heading: - it can be false or some label (string)
Regarding the allow_destroy: - you can set it check for the user Administrator privilege's as can seen here
Important - In the Physician model, make sure to have
accepts_nested_attributes_for :appointments, allow_destroy: true
And, in the active admin model file - admin\physicians.rb - set this:
permit_params :name, appointments_attributes: [:patient_id, :_destroy, :id]
I'm working in Rails 2, and my model look like this:
class Site < ActiveRecord::Base
has_many :contacts
def primary_contact
Contact.find :first, :conditions => {:site_id => self,
:primary_contact => true}
end
def primary_contact= new_primary_contact
contact = Contact.find(new_primary_contact)
contact.primary_contact = true
contact.save
end
end
Note that the :primary_contact virtual attribute is initialized in the model, so the default value should be present.
The form for #site in my view contains this input:
<%= form.input :primary_contact, :as => :check_boxes, :collection => (Contact.find(:all, :conditions => {:site_id => #site.id}, :order => "first_name ASC")), :label => false, :include_blank => false %>
This gives me a list of checkboxes, with the correct default checkbox already checked (ie the primary contact for that site is selected). However, I want this in the form of radio buttons or a select drop-down, and in those two cases, just by changing :as => :check_boxes to :as => :select or :as => :radio, the default isn't selected.
I also tried specifying the collection as just :collection => #site.contacts, but same thing.
Any idea what I'm doing wrong?
Which version of Formtastic? Sounds like it could be a bug. If you can still repeat after upgrading to Formtastic 1.2.4, please file an issue on Github.
I would like to assign two different "types" of tags (sector categories and free tagging) to a Company model using acts_as_taggable_on. NB: I'm new to RoR!
This is easy to do if just using standard text input fields, but I would like to use check-boxes on one type (a fixed sector category tag that is predefined), and then allow the user to add comma separated tags in an input field.
I have played around with this problem in various ways,... one inspired by this question...but I cannot get it to work
Here is what I have so far:
# models/company.rb
class Company ...
acts_as_taggable_on :tags, :sectors
has_many :taggings,
:as => :taggable,
:include => :tag,
:class_name => "ActsAsTaggableOn::Tagging",
:conditions => { :taggable_type => "Company" }
has_many :sector_tags,
:through => :taggings,
:source => :tag,
:class_name => "ActsAsTaggableOn::Tag",
:conditions => {:context => "sectors"}
end
in the form (using simple_form gem) I have...
# views/companies/_form.html.haml
= simple_form_for #company do |f|
= f.input :name
= f.association :sector_tags, :as => :check_boxes, :hint => "Please click all that apply"
= f.input :tag_list
= f.button :submit, "Add company"
And in my Company controller I have
# controllers/companies_controller.rb
def create
#company = current_user.companies.build(params[:company])
if #company.save
...
end
But this causes a validation error:
ActiveRecord::RecordInvalid in CompaniesController#create
Validation failed: Context can't be blank
Can anyone hint at how I can do this right?
A related question is if this is a good way to do it at all? Would I be better off just using a Category model for assigning sector tags through a joint model?
Thanks!
Well, I solved my problem. And it turned out to be quite simple. Alas, I ended up creating a separate Sector model through a joint "sectorizations" table. But if anyone is interested, I just wanted to update on what I did in the case above...
In my company model
# models/company.rb
class Company ...
acts_as_taggable_on :tags, :sectors
...
end
in the form
# views/companies/_form.html.haml
= simple_form_for #company do |f|
= f.input :name
= f.input :sector_list, :as => :check_boxes, :collection => #sectors, :hint => "Please check all that apply"
= f.input :tag_list
= f.button :submit, "Add company"
and in the company controller (create)
# controllers/company_controllers.rb
def new
#company = Company.new
#sectors = get_sectors
end
def get_sectors
sectors = []
for sector in Company.sector_counts
sectors << sector['name']
end
return sectors
end
It seems that act_as_taggable_on uses single table inheritance, so you actually don't need to create any additional tables. However you do need to follow their convention (that they never stated) as follows:
//add to model
attr_accessible :yourfieldname_list
acts_as_taggable_on :yourfieldname
//view
<%= f.text_field :yourfieldname_list %>