I have a has_many through association. When I go to the Store form I need to save Owner data in the same form. But I keep getting Unpermitted parameters: :offices. I tried with inverse_of as well. I tried changing the models structures like trying to accept attributes for all models.
Office Model:
class Office < ApplicationRecord
has_many :owner_offices, :dependent => :destroy
has_many :owners, through: :owner_offices
accepts_nested_attributes_for :owner_offices
#accepts_nested_attributes_for :offices
end
Owner Model:
class Owner < ApplicationRecord
has_many :owner_offices
has_many :offices, through: :owner_offices
accepts_nested_attributes_for :owner_offices
end
Owner_Office Model:
class OwnerOffice < ApplicationRecord
belongs_to :office
belongs_to :owner
accepts_nested_attributes_for :owner
end
Office Controller:
def new
#office = Office.new
#office.owners.build
end
def office_params
params.require(:office).permit(:office_name, :office_slug, :office_email, :phone, :office_type, :status, :mf_member, :comment,
:owners_attributes => [:office_id, :owner_id, :first_name, :last_name, :owner_email])
end
Office Form:
<%= form_with(model: office, local: true, html: {class: "form-office"}) do |form| %>
<div class="row">
<div class="col-md-6 col-sm-6 col-xs-12">
<div class="form-group">
<span><%= form.label :office_email %></span>
<%= form.text_field :office_email, class: 'form-control' %>
</div>
</div>
</div>
<hr>
<h3>Owner Information</h3>
<hr>
<%= form.fields_for :owners do |owner_form| %>
<div class="row">
<div class="col-md-6 col-sm-6 col-xs-12">
<div class="form-group">
<span><%= owner_form.label :first_name %></span>
<%= owner_form.text_field :first_name, class: 'form-control' %>
</div>
</div>
<div class="col-md-6 col-sm-6 col-xs-12">
<div class="form-group">
<span><%= owner_form.label :last_name %></span>
<%= owner_form.text_field :last_name, class: 'form-control' %>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-sm-6 col-xs-12">
<div class="form-group">
<span><%= owner_form.label :owner_email %></span>
<%= owner_form.text_field :username, class: 'form-control' %>
</div>
</div>
</div>
<% end %>
<% end %>
I just placed most of the part where I'm calling the fields_for for owner. So I'm stuck, not sure what I'm missing at the moment and I've been checking other resources as well, implementing a different logic.
Also, I do not want to use cocoon because is important to me to learn how to implement from scratch.
Thanks in advance.
Related
So, I have a model Label which is polymorphic and another model Stuff which is not. A stuff can have many labels (may also called groups), and each and every one of them can also have a label. I am working with the Cocoon gem to try to add these resource on to a single edit/new form (the Stuff one). The problem is that when I try to update the stuff with a new group (with new labels in it), it says this Labels labels labelable must exist. I think that that's an error given because the first label(group) is not yet saved to the database, so it can't give his nested label an id. (not sure though)
Also, is this the best way to do that? I mean, I made the label polymorphic only because I needed to save a only a string, and it would be unpractical and it would have taken database storage for nothing...
Enough talking, here's my code:
<div class="form-group">
<label>Groups:</label>
<div id="group" class="col-md-12 p-0 pl-md-3">
<%= form.fields_for :labels do |groupForm| %>
<%= render 'group_fields', f: groupForm %>
<% end %>
<div class="text-center">
<%= link_to_add_association 'Add Group', form, :labels, partial: 'group_fields', class: 'btn btn-success',
wrap_object: Proc.new { |group| group.labels.build; group } %>
</div>
</div>
</div>
that's in my _form.html.erb
<div class="nested-fields">
<div class="field form-group row">
<%= f.label :name, class: 'col-sm-1 col-form-label' %>
<div class="col-sm-10">
<%= f.text_field :name, class: 'form-control ml-2' %>
</div>
<div class="col-sm-1 p-0">
<%= link_to_remove_association "×".html_safe, f, class: 'badge badge-pill badge-danger mt-2' %>
</div>
<div class="col-12">
<div id="label" class="col-md-12 p-0 pl-md-5 pt-2">
<%= f.fields_for :labels do |labelForm| %>
<%= render 'label_fields', f: labelForm %>
<% end %>
<div class="text-center">
<%= link_to_add_association 'Add Label', f, :labels, class: 'btn btn-success' %>
</div>
</div>
</div>
</div>
</div>
that's in _group_fields.html.erb
<div class="nested-fields">
<div class="field form-group row mb-2">
<%= f.label :name, class: 'col-sm-1 col-form-label' %>
<div class="col-sm-10">
<%= f.text_field :name, class: 'form-control ml-2' %>
</div>
<div class="col-sm-1 p-0">
<%= link_to_remove_association "×".html_safe, f, class: 'badge badge-pill badge-danger mt-2' %>
</div>
</div>
</div>
and that's in my _label_fields.html.erb
class Label < ApplicationRecord
belongs_to :labelable, polymorphic: true
has_many :labels, as: :labelable, dependent: :destroy
accepts_nested_attributes_for :labels, allow_destroy: true, reject_if: proc { |att| att[:name].blank? }
end
this is my Label model
class Stuff< ApplicationRecord
has_many :labels, as: :labelable, dependent: :destroy
accepts_nested_attributes_for :labels, allow_destroy: true, reject_if: proc { |att| att[:name].blank? }
end
and this is my Stuff model
I forgot to mention that if I add only the first "layer" of label (group) without writing anything on the labels (2nd "layer") and I submit the form (which I can do and it updates the database as well) when I come back and edit I can actually modify the 2nd "layer" without any problems.
A belongs_to relation-ship is by default "required". This means it has to be filled in upon saving. However, when saving an item with nested childs, no id's are yet known and while obvious, rails has no way of knowing the belongs-to association will be set when saving them together.
There are two ways to handle this:
make the belongs_to optional, this will skip the validation, and the save will work. Something like belongs_to :labelable, polymorphic: true, optional: true
better, declare the inverse_of so rails knows when saving the labels it corresponds to the labelable relationship.
Like so:
has_many :labels, as: :labelable, dependent: :destroy, inverse_of: :labelable
You can declare the inverse_of on any assocation, so also on the belongs_to, but in most it suffices to just declare it on the has_many. It might not be enough in your specific scenario.
I am trying to have my Edit form only allow for the creation of new elements. Currently it automatically displays all of the existing elements. Below is my current code. I have a standard has_many, belongs_to relationship between Orders and Documents. I only want the ability for users to add new documents and never edit the existing documents. With the current code It displays all associated Documents on the edit form.
<%= f.fields_for :documents, child_index: Time.now.to_i do |document| %>
<div class="col-md-5">
<%= document.label :doc_type, "Type", :style => "color:red;" %>
<%= document.collection_select :doc_type_id, DocType.order(:name), :id, :name, { prompt: true, class: "form-full"} %>
<br>
</div>
<div class="col-md-7">
<%= document.label :description,"Description **", :style => "color:red;" %>
<%= document.text_field :description, style:"color:black;" %>
<br>
</div>
<div class="col-md-12">
<br>
<%= document.file_field :doc, style:"color:white;" %>
</div>
<div class="col-md-12" style="background:#272727;">
<hr class="style2">
</div>
<% end %>
class Order < ActiveRecord::Base
belongs_to :user
has_many :properties, :dependent => :destroy
has_many :documents, :dependent => :destroy
accepts_nested_attributes_for :documents,
:allow_destroy => true,
:reject_if => :all_blank
accepts_nested_attributes_for :properties,
reject_if: proc { |att| att["city"].blank? }
end
class Document < ActiveRecord::Base
belongs_to :order
belongs_to :doc_type
end
With The below code I was able to have the form appear correctly (not showing existing Documents) but when adding a new Document via the Edit form, the Document is never actually created.
<% if !current_page?(action: 'edit') %>
<%= f.fields_for :documents, child_index: Time.now.to_i do |document| %>
<div class="col-md-5">
<%= document.label :doc_type, "Type", :style => "color:red;" %>
<%= document.collection_select :doc_type_id, DocType.order(:name), :id, :name, { prompt: true, class: "form-full"} %>
<br>
</div>
<div class="col-md-7">
<%= document.label :description,"Description **", :style => "color:red;" %>
<%= document.text_field :description, style:"color:black;" %>
<br>
</div>
<div class="col-md-12">
<br>
<%= document.file_field :doc, style:"color:white;" %>
</div>
<div class="col-md-12" style="background:#272727;">
<hr class="style2">
</div>
<% end %>
<% else %>
<%= f.fields_for #order.documents.build, child_index: Time.now.to_i do |document| %>
<div class="col-md-5">
<%= document.label :doc_type, "Type", :style => "color:red;" %>
<%= document.collection_select :doc_type_id, DocType.order(:name), :id, :name, { prompt: true, class: "form-full"} %>
<br>
</div>
<div class="col-md-7">
<%= document.label :description,"Description **", :style => "color:red;" %>
<%= document.text_field :description, style:"color:black;" %>
<br>
</div>
<div class="col-md-12">
<br>
<%= document.file_field :doc, style:"color:white;" %>
</div>
<div class="col-md-12" style="background:#272727;">
<hr class="style2">
</div>
<% end %>
<% end %>
Any help/advice/resources would be appreciated. Been stuck on this for a bit. Also I have not refactored into partials yet so please forgive the messiness.
THANKS!!
-Vinny
I have an issue where a validation is suddenly not working. The field is a select box, and it's not setting the value. So when I try to submit the form, it says that Payee can't be blank. This is a 1 to 1 relationship between Expense and Payee. What happened? Do you see any issues here?
The field in question. It's in a helper but I've tried putting it back into the form with no luck.
def expense_payee_id_field(f)
f.select :payee_id, Payee.all.collect { |p| [p.display_name, p.id] }, { prompt: "Choose Payee"},{class:"fluid ui dropdown"}
end
The form:
<%= form_for #expense, html: { :class => "ui form segment" }, :remote => true do |f|%>
<div class="field">
<%= f.label :date%>
<div class="ui small input">
<%= f.date_field :date %>
</div>
</div>
<div class="field">
<%= f.label :amount %>
<div class="ui small input">
<%= f.text_field :amount %>
</div>
</div>
<div class="field">
<%= f.label :check_number %>
<div class="ui small input">
<%= f.text_field :check_number %>
</div>
</div>
<div class="field">
<%= f.label :payee %>
<div class="ui input">
<%= expense_payee_id_field(f)%>
</div>
</div>
<%= f.submit class: "ui blue button" %>
<% end %>
My models:
expense.rb
class Expense < ApplicationRecord
has_one :payee
monetize :amount_cents
has_many :expense_expense_categories, inverse_of: :expense
has_many :expense_categories, through: :expense_expense_categories, :dependent => :destroy
accepts_nested_attributes_for :expense_expense_categories,:allow_destroy => true
validates_associated :expense_expense_categories
validates :date, presence: true
validates_numericality_of :amount, presence: true, greater_than: 0
validates :expense_expense_category_ids, presence: true
validates_presence_of :payee_id
end
payee.rb
class Payee < ApplicationRecord
belongs_to :expense
validate :company_or_name
def full_name
[first_name, last_name].join(" ")
end
def display_name
if company.blank?
full_name
else
company
end
end
private
def company_or_name
if company.blank? && first_name.blank?
errors[:base] << "You must specify company or name"
end
end
end
Following the railscast #196 on nested forms... I have the following models:
class DealContact < ActiveRecord::Base
belongs_to :deal
belongs_to :contact
class Contact < ActiveRecord::Base
has_many :deal_contacts
has_many :deals, through: :deal_contacts
accepts_nested_attributes_for :deal_contacts, :allow_destroy => true
class Deal < ActiveRecord::Base
has_many :deal_contacts
has_many :contacts, through: :deal_contacts
accepts_nested_attributes_for :deal_contacts, :allow_destroy => true
In my deals form I have this
<div class="row">
<div class="span12"><h4>Contacts Associated with this Deal</h4></div>
<%= f.fields_for :deal_contacts do |builder| %>
<%= render 'deal_contact_fields', f: builder %>
<% end %>
<div class="span1"><%= link_to_add_contact "Add", f, :deal_contacts %></div>
</div>
</div>
And deal_contact_fields just contains:
<fieldset>
<div class="span4">
<%= f.association :contact, collection: Contact.all(order: 'contact_name'), label_method: :full_desc %>
</div>
<div class="span6">
<%= f.label :details, "Details " %>
<%= f.text_field :details %>
</div>
<div class="span1" style="margin-top: 30px">
<%= f.hidden_field :_destroy %>
<%= link_to "remove", '#', class: "remove_fields" %>
</div>
</fieldset>
This all works great for editing existing deals, however when I create a new one I get the following error:
undefined method `association' for #<ActionView::Helpers::FormBuilder:0x007fe6fba55840>
:-(
.association is only available in simple_form gem
You'll have to use collection_select to achieve what you want without that gem:
<%= f.collection_select :contact, Contact.all(order: 'contact_name'), :id, :name %>
I have following 2 models
class Watersporttyp < ActiveRecord::Base
attr_accessible :name
has_many :activities
has_many :watersportspots, through: :activities
end
class Watersportspot < ActiveRecord::Base
attr_accessible :watersporttyp_ids, :latitude, :longitude, address
belongs_to :user
has_many :activities
has_many :watersporttyps, through: :activities
reverse_geocoded_by :latitude, :longitude
end
In my View I have this search form
<%= form_tag watersportspots_path, :method => 'get' do %>
<div class="row collapse">
<div class="small-10 columns">
<%= text_field_tag :search, params[:search] %>
</div>
<div class="small-2 columns">
<%= submit_tag "Search", :name => nil, :class => "button prefix" %>
</div>
</div>
<div class="row">
<div class="small-12 columns">
<% Watersporttyp.all.each do |watersporttyp| %>
<%= check_box_tag "typs[]", watersporttyp.id %>
<%= watersporttyp.name %><br>
<% end %>
</div>
</div>
<% end %>
My question is how do I set up my controller to perform search by filtering nearby location with the attributes from the checkboxes "types[]"
I tried this in my controller, but it doesn't work
#watersportspots = Watersportspot.near(params[:search], 50, :order => :distance, :units => :km).join(:watersporttyp).where(:watersporttyp => params[:typs])
I'm using the geocoder gem for geocoding and my system is using ruby 1.9.3 and Rails 3.2