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.
Related
I have created a valuation table which contain
class CreateValuations < ActiveRecord::Migration
def change
create_table :valuations do |t|
t.text :location
t.integer :number_of_bedroom
t.integer :number_of_bath
t.integer :age_of_building
t.text :other_details
t.string :name
t.string :email
t.integer :contact_number
t.timestamps null: false
end
end
end
And later i added a column :building of type text in it using rails generate migration add_building_to_valuations building:text. I have created a form
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#valuation) do |val| %>
<%= val.label :building, "Name of Building/Builder" %>
<%= val.text_field :building, class: 'form-control' %>
<%= val.label :location, "Location" %>
<%= val.text_field :location, class: 'form-control' %>
<%= val.label :number_of_bedroom, "Number of Bedroom" %>
<%= val.text_field :number_of_bedroom, class: 'form-control' %>
<%= val.label :number_of_washroom, "Number of Washroom" %>
<%= val.text_field :number_of_bath, class: 'form-control' %>
<%= val.label :age_of_building, "Age of Building" %>
<%= val.text_field :age_of_building, class: 'form-control' %>
<%= val.label :name, "Name" %>
<%= val.text_field :name, class: 'form-control' %>
<%= val.label :email, "Email" %>
<%= val.text_field :email, class: 'form-control' %>
<%= val.label :contact_number, "Contact Number" %>
<%= val.text_field :contact_number, class: 'form-control' %>
<%= val.submit "Evaluate my property", class: "btn btn-primary" %>
<% end %>
</div>
</div>
When i fill all the field and submit via Evaluate my property, Then no data is being saved in :building.
I checked this using following commands
$ rails console
$ Valuation.all
and received output are following output
#<Valuation id: 1, location: "Chandivali, Powai",
number_of_bedroom: 3, number_of_bath: 3,
age_of_building: 9, other_details: nil, name: "Shravan",
email: "shravan.xxx#gmail.com",
contact_number: "9876543210",created_at: "2015-11-14 09:47:26",
updated_at: "2015-11-14 09:47:26", building: nil>,
You should update your valuation_params Which is most likely a private function
private
def valuation_params
params.require(:valuation).permit(:building,
:location,
:number_of_bedroom,
:number_of_bath,
:age_of_building,
:name, :email, :contact_number)
end
end
I am trying to create a book consultation form with following fields from two models
User Model
- first_name
- last_name
- email
- contact_number
Message Model
:message_text
The desired form rendered should be presenting the user all the User Model fields along with a text area which would be :message_text for the Message Model.
The code of User Model is
class User < ActiveRecord::Base
has_many :messages
validates :first_name , presence: true
validates :last_name , presence: true
validates :email, presence: true
validates :contact_number,presence: true
accepts_nested_attributes_for :messages
end
The Code of Message Model
class Message < ActiveRecord::Base
validates :message_text, presence: true
belongs_to :user , :class_name => 'User', :foreign_key => 'id'
end
The index controller of User which renders the form looks like
def index
#users = User.all
#user = User.new
#user.messages.build
end
The view file looks like
<%= form_for(#user) do |f| %>
<div class="form-group">
<%= f.label :first_name %>
<%= f.text_field :first_name %>
</div>
<div class="form-group">
<%= f.label :last_name %>
<%= f.text_field :last_name %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<div class="form-group">
<%= f.label :contact_number %>
<%= f.text_field :contact_number %>
</div>
<div class="form-group">
**the fields_for does not get rendered at all into the HTML**
<%= f.fields_for :messages do |ff| %>
<%= ff.label :message_text %>
<%= ff.text_field :message_text %>
<% end %>
</div>
<div class="btn primary-btn">
<%= f.submit 'Book Free Consultation'%>
</div>
All other fields get rendered. Can anybody please help me in spotting the mistake . Thank you in advance
your migration file should be like below
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
t.string :first_name
t.string :last_name
t.string :email
t.string :contact_number
end
end
end
class CreateMessages < ActiveRecord::Migration
def change
create_table(:messages) do |t|
t.string :message_text
t.references :user, index: true
end
end
end
I have two objects in my app: user which has a unique parameter email_address and node which has a name and belongs to a user.
Here is my two objects in the DB, Node:
class CreateNodes < ActiveRecord::Migration
def change
create_table :nodes do |t|
t.string :name
t.references :user, index: true, foreign_key: true
t.timestamps null: false
end
end
end
And User:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :email_address, unique: true, index: true
t.timestamps null: false
end
end
end
My form to add a node looks like this:
<%= form_for #node do |f| %>
<%= f.text_field :name, :class => "form-control" %>
<%= f.number_field :user_id, :class => "form-control" %>
<%= f.submit 'Add the node' %>
<% end %>
However, I would like to use the user's email_address parameter instead of his/her id for convenience. I already did the changes in my controller to find the id linked to the email address but my new form returns an error, here it is:
<%= form_for #node do |f| %>
<%= f.text_field :name, :class => "form-control" %>
<%= f.email_field :user_email_address, :class => "form-control" %>
<%= f.submit 'Add the node' %>
<% end %>
The error:
undefined method `user_email_address' for #<Node id: nil, name: nil, user_id: nil>
The problem returned is clear but I don't know how to add this method and still follow the best practices for RoR development, any suggestions?
When you have the below line :
<%= f.email_field :user_email_address, :class => "form-control" %>
The f object, which is a Node object, calling the method user_email_address on itself. As there is no such method, you are getting the error.
Add a method inside the Node model:
def user_email_address
self.user.email_address
end
After adding the above method, below will work :
<%= f.email_field :user_email_address, :class => "form-control" %>
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' %>
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])