I have an Active Admin form where I need to be able to update/add a polymorphic relationship to an object. I can get the form to display it, but it won't update the table with the polymorphic relationship. The models are Category and TargetArea and they both have Tags. Here is the model setup:
#category.rb
class Category < ActiveRecord::Base
has_many :tags, as: :taggable
accepts_nested_attributes_for :tags
end
#tag.rb
class Tag < ActiveRecord::Base
belongs_to :category
belongs_to :target_area
belongs_to :taggable, polymorphic: true
accepts_nested_attributes_for :taggable
end
#Active Admin Form for Categories
permit_params :name, tags: []
form do |f|
f.actions
f.inputs 'Categories' do
f.input :name
f.inputs do
f.has_many :tags do |t|
t.input :name
end
end
end
f.actions
end
I want to be able to update and create new categories and add tags to the category in the form. I can't seem to find an example that does the same thing and this just doesn't seem to work.
Related
Here are 2 models: customer and address. A customer has_one address.
class Customer < ActiveRecord::Base
has_one :address
accepted_nested_attributes_for :address, :allow_destroy => true
end
class Address < ActiveRecord::Base
belongs_to :customer
validates :add_line, :presence => true
end
<% simple_form_for #customer do |f| %>
.....
<%=f.simple_fields_for :address do |builder| %>
<%=render ('address', f: builder) %>
<% end %>
<%end %>
address view
<%=f.input :add_line %>
address is nested attribute in customer. The problem we are having is that if address is modified wrongly (ex, a nil add_line) within customer view, there is no error (#customer.update_attributes in customer controller) popping up. Is there a way setting up the nested attributes in such a way nil add_line will fail the update?
Two things caught my eye with your original post:
One,remember that you need a belongs_to :customer in the Address model.
Two, you need to add a validation in the Customer model
class Customer < ActiveRecord::Base
has_one :address
accepted_nested_attributes_for :address, allow_destroy: true, reject_if: :address_invalid
private
def address_invalid(attributes)
# add custom validation code here ...
end
end
Models: I have a Company model that has_many Tasks. Each Task has_one Employee.
Task model:
class Task < ActiveRecord::Base
belongs_to :company
has_one :employee, dependent: :destroy
accepts_nested_attributes_for :employee
validates_associated :noteholder
end
Employee model:
class Employee < ActiveRecord::Base
belongs_to :task
validates :name, presence: true, uniqueness: { case_sensitive: false }
end
Form: I created a nested form for Task that accepts_nested_attributes_for the Employee model. The form has an Employee name field with an autocomplete function that loads all Company.employees.
_form.html.erb form:
<%= simple_form_for(#task) do |f| %>
<%= f.simple_fields_for :employee do |employee| %>
<%= employee.input :name, input_html: { data: { autocomplete_source: #employees.pluck(:name).to_json } } %>
<% end %>
<%= f.button :submit, 'Save' %>
<% end %>
This saves a new record for each employee, regardless of whether or not an employee with that name exists
Desired behaviour:
If the user fills in a new Employee the model should create a new record, whereas if it would provide an existing Employee name, it should not.
My attempt: I thought the find_or_create_by method would be useful here, but have had no success with implementing it.
Question: How do I correctly set up my model sothat the Employee model only saves a new employee if the employee name does not yet exist?
I need help with a create form for a has_many_through association which also specifies a class name:
class Sponsor < ActiveRecord::Base
has_many :member_contacts
has_many :contacts, through: member_contacts, class_name: :member
accepts_nested_attributes_for :address, :contacts
end
class Contact < ActiveRecord::Base
has_many :member_contacts
has_many :sponsors, through: member_contacts
end
class MemberContact < ActiveRecord::Base
belongs_to :contact
belongs_to :sponsor
end
sponsors_controller.rb
def create
#sponsor = Sponsor.create(sponsor_params)
#sponsor.contacts.build
end
def sponsor_params
params.require(:sponsor).permit(:name,:website,:email,
:contact_first_name, :contact_surname, contacts_attributes: [], address_attributes: [:flat, :street, :postal_code, :city])
end
sponsor/_form.html.haml
= simple_form_for #sponsor do |f|
= f.association :contacts, collection: Member.all, label_method: :full_name
This is failing with the error 'unpermitted params, contact_ids', because
"contact_ids"=>["", "4", "5", "6"]
is being passed in the params hash. In the form I'd like a drop down list of all the members and the ability to select multiple members which will be saved against the sponsor as contacts.
How do I set up the contacts_attributes in sponsor_params in the controller and the collection_select simple_form helper in the view?
To get the form working, I added a foreign key to the sponsor class
has_many :contacts, through: member_contacts, class_name: 'Member', foreign_key 'member_id'
changed the strong params in the controller
def sponsor_params
params.require(:sponsor).permit(:name,:website,:email, contact_first_name, :contact_surname, contact_ids: [], address_attributes: [:flat, :street, :postal_code, :city])
end
and removed the association in the view, using collection_select
= f.collection_select :contact_ids, Member.all, :id, :full_name,
{ selected: #sponsor.contacts.map(&:id) }, { multiple: true }
You can set like this:
params.require(:sponsor).permit(:name,:website,:email, contact_ids: []...)
Note that permit(:contact_ids) will fail, but permit(contact_ids: []) works.
I have been trying to create a relationship like the database listed below, using devise to create the Customer table. I have created migrations for the other tables using the ID ing though table-names and ID. My models look like the below. I know I have gone overboard with the has_many relationships, but I have been trying this all day.
Can anyone help or show the correct way to set up this so that I can create, edit and update addresses on the user. I have managed success with simple nested attributes say Customer/ Direct to address but when I place the table in the middle I just cant get the address attributes to show or update.
I guess there is a more complex edit, create , destroy method that needs to be implemented also.
I'm also getting lost with how to allow strong params on this type of nesting as most examples i can find only have it connected to tables that hold the user_id in them and not one that is connected through another table.
cheers in advance for the guidance.
DataModel image here
Tables
customers / Devise table defaults
customer_addresses
id
address_id
address_type_id
customer_id
addresses
id
address xzy Marua Road
other details / Front house
address_type
id
address_type / Home , Business etc
address_type_description / Where you live etc
class Customer < ActiveRecord::Base
has_many :customer_addresses
has_many :addresses
has_many :address_types
accepts_nested_attributes_for :customer_addresses
accepts_nested_attributes_for :address_types
accepts_nested_attributes_for :addresses
end
class UserAddress < ActiveRecord::Base
has_many :customer
has_many :address_types
has_many :addresses
end
class AddressType < ActiveRecord::Base
belongs_to :customer_address
end
class Address < ActiveRecord::Base
belongs_to :user_address
end
<div class="field">
<%= f.fields_for :user_addresses do |ff| %>
<div>
<%= ff.label :address_id %><br />
<%= ff.text_field :address_id %>
<%= ff.fields_for :address do |fff| %>
<%= fff.label :address %><br />
<%= fff.text_field :address %>
<% end %>
<% end %>
</div>
</div>
user controller params
def user_params
params.require(:user).permit(:id, :username, :first_name, :last_name, :email, :password, :password_confirmation,
user_address_attributes:[:user_is, :address_id, :address_type_id],
addresses_attributes:[:id, :address, :other_address_details ],
address_type_attributes:[ :id, :address_type])
end
The associations you defined should have been like the following
class Customer
has_many :customer_addresses
has_many :addresses, :through => :customer_addresses
has_many :address_types, :through => :customer_addresses
end
class Address
has_many :customer_addresses
has_many :customers, :through => :customer_addresses
has_many :address_types, :through => :customer_addresses
end
class AddressType
has_many :customer_addresses
has_many :customers, :through => :customer_addresses
has_many :addresses, :through => :customer_addresses
end
class CustomerAddress
belongs_to :customer
belongs_to :address
belongs_to :address_type
end
class Customer < ActiveRecord::Base
has_many :customer_addresses
accepts_nested_attributes_for :customer_addresses
end
class AddressType
has_many :customer_addresses
end
class CustomerAddress
belongs_to :address_type
belongs_to :customer
belongs_to :address
accepts_nested_attributes_for :address
after_initialize :add_address, unless: 'address.present?'
def add_address
self.build_address
end
end
I'm working through creating a has_many: through relationship in active admin. Here are the models as they stand:
class Category < ActiveRecord::Base
has_many :subcategories
end
class Subcategory < ActiveRecord::Base
has_many :product_in_subcategories
has_many :products, through: :product_in_subcategories
accepts_nested_attributes_for :product_in_subcategories, :allow_destroy => true
belongs_to :category
end
class Product < ActiveRecord::Base
has_many :product_in_subcategories
has_many :subcategories, through: :product_in_subcategories
accepts_nested_attributes_for :product_in_subcategories, :allow_destroy => true
end
class ProductInSubcategory < ActiveRecord::Base
belongs_to :product
belongs_to :subcategory
end
In ActiveAdmin I have the permit_params and form like so:
ActiveAdmin.register Product do
# note some params that are product only have been removed for simplicity
permit_params :name, subcategory_id:[:id], product_in_subcategories_attributes: [:id, :subcategory_id, :product_id, :_create, :_update]
form do |f|
f.inputs
f.has_many :product_in_subcategories do |s|
s.input :subcategory_id, :as => :check_boxes, :collection => Subcategory.all
end
f.actions
end
end
The form populates as should, and will save everything except for the subcategory_id. If I enter into the DB a proper subcategory_id the box will show checked on edit.
The messages when saving give:
Unpermitted parameters: subcategory_id
However, it appears it is trying to submit this with the product, for which there isn't a subcategory_id. Any ideas on what I am doing incorrectly here? This is driving me nuts and I've read everything I can find. I'd really like to understand what I'm doing wrong. Thanks.
After much time spent on this one, I couldn't find a suitable solution except for this one, which is actually very nice. It in fact is not much different from my envisioned solution:
The only changes to the above code were made in ActiveAdmin:
ActiveAdmin.register Product do
# note some params that are product only have been removed for simplicity
permit_params :name, product_in_subcategories_attributes: [:id, :subcategory_id, :product_id, :_create, :_update]
form do |f|
f.inputs
f.has_many :product_in_subcategories do |s|
s.input :subcategory_id, :as => :select, :collection => Subcategory.all
end
f.actions
end
end
Very strange how this allows a select box with no issues, but it flips out over check boxes. Nonetheless, I'm happy with the solution.