I have a serialized object :address in Hotel class. When I'm trying to save data using the form, it all saves fine. All except :address. No errors, nothing... Tried different variants, please help.
Here is my code:
migrations
class CreateHotels < ActiveRecord::Migration
def change
create_table :hotels do |t|
t.string :title
t.integer :user_id
t.integer :stars
t.text :room
t.decimal :price
t.text :address
t.timestamps
end
add_index :hotels, [:user_id, :created_at]
end
end
hotel.rb
class Hotel < ActiveRecord::Base
belongs_to :user
default_scope -> { order('created_at DESC') }
validates :title, presence: true, length: { maximum: 80 }
validates :stars, presence: true
validates :room, length: { maximum: 800 }
validates :user_id, presence: true
serialize :address, Hash
end
new.html.erb
<%= form_for(#hotel) do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :stars %>
<%= f.text_field :stars %>
<%= f.label :room, "Room description" %>
<%= f.text_area :room, size: "20x10" %>
<%= f.label :price %>
<%= f.number_field :price %>
<%= f.fields_for :address, OpenStruct.new(f.object.address || {}) do |o| %>
<%= o.label :country %>
<%= o.text_field :country %>
<%= o.label :state %>
<%= o.text_field :state %>
<%= o.label :city %>
<%= o.text_field :city %>
<%= o.label :street %>
<%= o.text_field :street %>
<% end %>
<% end %>
In your hotels_controller.rb have you permitted address params?
params.require(:hotel).permit(address: [:country, :state, :city, :street])
Related
I'm trying to create nested attributes but I'm getting the following error "Unpermitted parameter: address_fields" the fields appear when I'm trying to generate and create a new nested address but doesn't get saved.
In controller :
def praject_params
params.require(:praject).permit(:name, :cpf, :phone, :email, :zip, :city, :state, :borough, :street, :number, :comp, :type, address_attributes: [ :id, :ziptwo, :citytwo, :statetwo, :boroughtwo, :streetwo, :numbertwo, :comptwo, :typetwo])
end
In address model :
class Address < ApplicationRecord
self.inheritance_column = :foo
belongs_to :praject, optional: true
end
In praject model :
class Praject < ApplicationRecord
self.inheritance_column = :foo
has_many :addresses, inverse_of: :praject, dependent: :destroy
accepts_nested_attributes_for :addresses, allow_destroy: true, reject_if: proc { |att| att['name'].blank?}
before_save do
self.type.gsub!(/[\[\]\"]/, "") if attribute_present?("type")
end
end
class CreateAddresses < ActiveRecord::Migration[5.0]
def change
create_table :addresses do |t|
t.string :ziptwo
t.string :citytwo
t.string :statetwo
t.string :boroughtwo
t.string :streetwo
t.string :numbertwo
t.string :comptwo
t.string :typetwo
t.belongs_to :praject, foreign_key: true
t.timestamps
end
end
end
In the _form.html.erb I just have a button to add a new nested address field.
The funny part is that this error appear in the console when the rails application is running and I'm trying to create a new project, I tried to change the controller to addresses_attributes[] and is not working too. Can anyone help me? I'm getting crazy with this, I tried almost everything and nothing works.
## _form.html.erb
<%= f.error_notification %>
<%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
<th>
<div class="form-inputs">
<%= f.input :name, label: 'Name' %>
<%= f.input :cpf, label: 'Cpf' %>
<%= f.input :phone, label: 'Phone' %>
<%= f.input :email, label: 'Email' %>
<%= f.input :zip, label: 'Zip' %>
<%= f.input :city, label: 'City' %>
<%= f.input :state, label: 'State' %>
<%= f.input :borough, label: 'Neighbourhood' %>
<%= f.input :street, label: 'Street' %>
<%= f.input :number, label: 'Number' %>
<%= f.input :comp, label: 'Comp' %>
<div class="field">
<h4>Type:</h4>
<%= label_tag 'type_comer', 'Comercial' %>
<%= check_box_tag 'praject[type][]', 'comercial', checked('comercial'), id: 'type_comer' %>
<%= label_tag 'type_res', 'Residential' %>
<%= check_box_tag 'praject[type][]', 'Residential', checked('Residencial'), id: 'type_res' %>
<%= label_tag 'type_farm', 'Rural' %>
<%= check_box_tag 'praject[type][]', 'Rural', checked('Rural'), id: 'type_farm' %>
<%= label_tag 'type_beach', 'Beach' %>
<%= check_box_tag 'praject[type][]', 'Beach', checked('Beach'), id: 'type_beach' %>
</div>
</div>
<h3>Secondary Addresses:</h3>
</th>
<div class="field"
<%= form_for(#praject) do |f| %>
# ...
<%= f.fields_for(:addresses) do |address| %>
<%= address.input :cpf, label: 'Cpf' %>
<%= address.input :phone, label: 'Phone' %>
<%= address.input :email, label: 'Email' %>
<%= address.input :zip, label: 'Zip' %>
<%= address.input :city, label: 'City' %>
<%= address.input :state, label: 'State' %>
<%= address.input :borough, label: 'Neighbourhood' %>
<%= address.input :street, label: 'Street' %>
<%= address.input :number, label: 'Number' %>
<%= address.input :comp, label: 'Comp' %>
<% end %>
# ...
<% end %>
If you are using simple_form use its wrapped simple_fields_for method instead.
So I have a form and corresponding classes. I got an error:
undefined method `start' for #<Klass id: nil, name: nil, teacher: nil, day: nil>
for line: <%= f.text_field :start, class: 'form-control' %>
and (when I'm trying to delete the above one) <%= f.text_field :duration, class: 'form-control' %>
removing both fields makes my website ok.
My whole form code:
<%= form_for #klass do | f | %>
<div class = “form-group”>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :teacher %>
<%= f.text_field :teacher, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :start %>
<%= f.text_field :start, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :duration %>
<%= f.text_field :duration, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :day %>
<%= f.select :day, ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN'] %>
</div>
<%= f.submit 'Submit', class: 'btn btn-default' %>
</div>
<% end %>
model (changing integer to string doesn't make any difference, but that is the only difference betweenthese two fields and the rest of the form that I can see) :
class Klass < ActiveRecord::Base
validates :name, presence: true
validates :teacher, presence: true
validates :day, presence: true
validates :start, presence: true
validates :duration, presence: true, numericality: { only_integer: true }
end
database file:
class CreateKlasses < ActiveRecord::Migration[5.0]
def change
create_table :klasses do |t|
t.string :name
t.string :teacher
t.string :day
t.integer :start
t.integer :duration
end
end
end
and controller:
class KlassesController < ApplicationController
def new
#klass = Klass.new
end
end
Looks for me like I missed to declare these two form fields but where else I can look for it?
1- rake db:rollback
make sure you have these fields added in migration file
class CreateKlasses < ActiveRecord::Migration[5.0]
def change
create_table :klasses do |t|
t.string :name
t.string :teacher
t.string :day
t.integer :start
t.integer :duration
end
end
end
2- rake db:migrate
now reload rails console
reload!
or just close rails console and open rails console again.
check again Klass.new if it has all field that you added in migration. if those field exists then restart server and thats it.
In a implementation of gem: https://github.com/arvindvyas/Country-State-Select
When i go to Post Job new page show this error on the log
undefined method `country' for #<Job:0x007f8c07092320>
I've tried to put the
accepts_nested_attributes_for
in the job model, but did not worked.
Someone have any hint to spare?
Job Model
class Job < ActiveRecord::Base
belongs_to :user
belongs_to :location
accepts_nested_attributes_for :location, allow_destroy: true
default_scope -> { order(created_at: :desc) }
end
Location Model
class Location < ActiveRecord::Base
has_many :users
has_many :jobs
end
Job new view
<%= simple_form_for #job do |f| %>
<%= f.simple_fields_for :location do |l| %>
<%= l.input :country, label: "Country", collection: CountryStateSelect.countries_collection %>
<%= l.input :state, CountryStateSelect.state_options(label: "State / Province", form: f, field_names: { :country => :country, :state => :state } ) %>
<%= l.input :city, CountryStateSelect.city_options(label: "City ", form: f, field_names: { :state => :state, :city => :city } ) %>
<% end %>
<%= f.input :name, label: 'Name', error: 'Name is mandatory' %>
<%= f.input :description, placeholder: 'user#domain.com' %>
<%= f.button :submit %>
<% end %>
In the fields
<%= l.input :state, CountryStateSelect.state_options(label: "State / Province", form: f, field_names: { :country => :country, :state => :state } ) %>
<%= l.input :city, CountryStateSelect.city_options(label: "City ", form: f, field_names: { :state => :state, :city => :city } ) %>
you have form: f, but you are within a simple_fields_for block which is currently using l instead of f
Looks like you're missing a country field in your Job model. Add it using a migration:
add_column :jobs, :country, :string
I added a nested attribute to my form, the fields for the nested attribute which is Education fields do not render, the other fields do. The relationships appear to be in order and the controller does too.
Here is the code.
Controller
def new
#profile = current_user.build_student_profile
end
def profile_params
params.require(:student_profile).permit(:first_name, :last_name, :gender, student_profiles_attributes: [:degree, :university_id, :major, :major2, :start_date, :end_date, :grade, :grade_scale] )
end
Models
class Education < ActiveRecord::Base
belongs_to :student_profile
belongs_to :university
validates :grade_scale, inclusion: { in: %w(GPA4 GPA7 WAM100) }
validates :degree, :university_id, :major, :start_date, :end_date, :grade, :grade_scale, presence: true
end
class StudentProfile < ActiveRecord::Base
belongs_to :user
has_many :educations
validates :gender, inclusion: { in: %w(male female) }
validates :first_name, :last_name, :gender, presence: true
accepts_nested_attributes_for :educations
end
Form
<%= form_for (#profile) do |f| %>
<%= f.label :first_name %>
<%= f.text_field :first_name %>
<%= f.label :last_name %>
<%= f.text_field :last_name %>
<%= f.label :gender %>
<%= f.text_field :gender %>
<%= f.fields_for :educations do |education_fields| %>
<%= education_fields.label :Degree %>
<%= education_fields.text_field :degree %>
<%= education_fields.label :University %>
<%= education_fields.collection_select(:university_id, University.all, :id, :name) %>
<%= education_fields.label :Major %>
<%= education_fields.text_field :major %>
<%= education_fields.label :Additional_Major %>
<%= education_fields.text_field :major2 %>
<%= education_fields.label :Start_Date %>
<%= education_fields.date_field :start_date %>
<%= education_fields.label :End_Date %>
<%= education_fields.date_field :end_date %>
<%= education_fields.label :Grade %>
<%= education_fields.number_field :grade %>
<%= education_fields.label :Grade_Scale %>
<%= education_fields.select :grade_scale, [["GPA / 4","GPA4"], ["GPA / 7","GPA7"], ["WAM / 100","WAM100"]] %>
<% end %>
<%= f.submit :submit %>
<% end %>
I have tried to add the following to the controller new action #profile.educations.build but I get an error unknown attribute student_profile_id
Can anyone help ?
Make sure you have student_profile_id attribute/column present in educations table.
After that, as you have mentioned, you need to build educations object on student_profile as:
def new
#profile = current_user.build_student_profile
#profile.educations.build
end
Try this
<%= f.fields_for(:educations,#profile.educations.build) do |education_fields| %>
<% end %>
or
def new
#profile = current_user.build_student_profile
#educations = #profile.educations.build
end
<%= f.fields_for(#educations) do |education_fields| %>
<% end %>
I have polymorphic associations with different models that I want to save upon submitting the registration form using devise. i.e:
User
Company + ContactInfo
Employee + ContactInfo
I understand that nesting forms is not recommended but What would be the best way to achieve this?
Thanks
models:
class User < ActiveRecord::Base
belongs_to :company
accepts_nested_attributes_for :company
end
class Company < ActiveRecord::Base
has_many :employees
has_one :contact_info, as: :contactable
accepts_nested_attributes_for :contact_info
end
class Employee < ActiveRecord::Base
belongs_to :company
has_one :contact_info, as: :contactable
accepts_nested_attributes_for :contact_info
end
class ContactInfo < ActiveRecord::Base
belongs_to :imageable, polymorphic: true
end
migrations:
class CreateCompanies < ActiveRecord::Migration
def change
create_table :companies do |t|
t.string :name
t.references :contact_info, index: true
t.string :website
t.timestamps null: false
end
add_foreign_key :companies, :contact_infos
end
end
class CreateEmployees < ActiveRecord::Migration
def change
create_table :employees do |t|
t.string :first_name
t.string :last_name
t.references :company, index: true
t.references :contact_info, index: true
t.string :job_title
t.timestamps null: false
end
add_foreign_key :employees, :contact_infos
end
end
class CreateContactInfos < ActiveRecord::Migration
def change
create_table :contact_infos do |t|
t.string :email
t.string :phone
t.string :mobile
t.string :contactable_type
t.integer :contactable_id
t.timestamps null: false
end
end
end
registration controller:
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up).push(:name, :email, :password, company_attributes: [ :id, :name, :website, :company_type, :number_of_employees, contact_info_attributes: [ :id, :email, :phone, :mobile]])
end
devise's new registration:
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :role => 'form'}) do |f| %>
<%= devise_error_messages! %>
<%= hidden_field_tag 'plan', params[:plan] %>
<% resource.build_company %>
<%= f.fields_for :company do |f| %>
<%= render "companies/fields", f: f %>
<% end %>
<% resource.company.build_contact_info %>
<%= f.fields_for :contact_info do |f| %>
<%= render "contact_infos/fields", f: f %>
<% end %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, :autofocus => true, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
</div>
<%= f.submit 'Sign up', :class => 'button right' %>
<% end %>
Console:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Nb6Na8P93s1dYvlDIQuiG11IoDeSzSylH4BCN8Tm7ipxCsbsdiWjDx5tJpijwldkjK4pPfjuwROnEvybYS7UIQ==", "plan"=>"free", "user"=>{"company_attributes"=>{"name"=>"Company Name", "website"=>"company website", "company_type"=>"company type", "number_of_employees"=>"121"}, "contact_info"=>{"email"=>"company#email.com", "phone"=>"1234", "mobile"=>"1234"}, "name"=>"user_name", "email"=>"user_email#email.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign up"}
Unpermitted parameter: contact_info
only User and company params are saving well. I was trying to get the devise_parameter_sanitizer to work with nesting contact_info in company first without trying the same with employee just yet, any idea what I'm doing wrong or any tips if im on the right track?
Thanks!
Update:
However contact_info params are permitted if I nest the contact_info form fields within the company form fields like so:
<% resource.build_company %>
<%= f.fields_for :company do |f| %>
<%= render "companies/fields", f: f %>
<% resource.company.build_contact_info %>
<%= f.fields_for :contact_info do |cf| %>
<%= render "contact_infos/fields", f: cf %>
<% end %>
<% end %>
the question is, is that good practice?
This is a guess - but your contact_info for the company isn't nested inside the company section. Try something like this (note, not tested, probably buggy)
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :role => 'form'}) do |f| %>
<%= devise_error_messages! %>
<%= hidden_field_tag 'plan', params[:plan] %>
<% resource.build_company %>
<%= f.fields_for :company do |f| %>
<%= render "companies/fields", f: f %>
<%# this is now nested inside the company-fields %>
<% resource.company.build_contact_info %>
<%= f.fields_for :contact_info do |f| %>
<%= render "contact_infos/fields", f: f %>
<% end %>
<% end %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, :autofocus => true, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
</div>
<%= f.submit 'Sign up', :class => 'button right' %>