I am always getting this error message:
NoMethodError in ListsController#new undefined method `fetch_value' for nil:NilClass
Extracted source (around line #8):
7 def new
8 #list = List.new
9 end
I don't get the reason for this error ^^
My routes.rb
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'lists#index'
get 'home' => 'lists#index', as: 'home'
get 'new' => 'lists#new', as: 'new'
resources :lists
end
Database name:
:lists
Model name:
list
lists_controller:
class ListsController < ApplicationController
def index
#lists = List.all
end
def new
#list = List.new
end
def show
#list = List.find(params[:id])
end
def create
#list = List.new(list_params)
if(#list.save)
redirect_to #list
else
render 'new'
end
end
def edit
#list = List.find(params[:id])
end
def update
#list = List.find(params[:id])
if(#list.update(list_params))
redirect_to #list
else
render 'edit'
end
end
def destroy
#list = List.find(params[:id])
#list.destroy
redirect_to lists_path
end
private def list_params
params.require(:list).permit(:date, :class, :lesson, :subject, :teacher, :room, :info)
end
end
new.html.erb
<%= form_for :list, url: lists_path do |f| %>
<% if #list.errors.any? %>
<% #list.errors.full_messages.each do |error| %>
<div class="alert alert-danger"><%= error %></div>
<% end %>
<% end %>
<div class="alert alert-info">Please fill out all the fields below.</div>
<p>
<%= f.label :date %><br>
<%= f.text_field :date, {:class => 'form-control'} %>
</p>
<p>
<%= f.label :class %><br>
<%= f.text_area :class, {:class => 'form-control'} %>
</p>
<p>
<%= f.label :lesson %><br>
<%= f.number_field :lesson, {:class => 'form-control'} %>
</p>
<p>
<%= f.label :subject %><br>
<%= f.text_field :subject, {:class => 'form-control'} %>
</p>
<p>
<%= f.label :teacher %><br>
<%= f.text_field :teacher, {:class => 'form-control'} %>
</p>
<p>
<%= f.label :room %><br>
<%= f.text_field :room, {:class => 'form-control'} %>
</p>
<p>
<%= f.label :info %><br>
<%= f.text_area :info, {:class => 'form-control'} %>
</p>
<p>
<%= f.submit({:class => 'btn btn-info'}) %>
</p>
<% end %>
Using the BootstrapCDN and only the default gems.
Thanks for any answers :)
In your model you have an attribute named class which is a reserved keyword which is causing issues. As I can see your code:
<p>
<%= f.label :class %><br>
<%= f.text_area :class, {:class => 'form-control'} %>
</p>
So you should never use reserved keywords as attributes because you are overriding it in that case. So when overriding it, your attribute will not consist of all the properties required by the language. That is why you are getting the error.
Rails is trying to fetch the attributes from :list which should be #list
Change the form_for in new.html.erb from
<%= form_for :list, url: lists_path do |f| %>
to
<%= form_for #list, url: lists_path do |f| %>
I have this model User, Entidade and Candidato.
class User < ActiveRecord::Base
has_one :entidade
has_one :candidato
accepts_nested_attributes_for :entidade
accepts_nested_attributes_for :candidato
class Candidato < ActiveRecord::Base
belongs_to :user
class Entidade < ActiveRecord::Base
belongs_to :user
Basically in order to register you need to specify if you want to be an Entidade or a Candidato. They have some shared attributes that i put in the User table. And the non shared attributes stay in the respective table.
This is the form:
<%= simple_form_for #user, :html => { :multipart => true } do |f| %>
<%= render 'shared/error_messages' %>
<%= f.input :email %>
<%= f.input :role, :as => :hidden, :input_html => { :value => "candidato" } %>
<%= f.input :password %>
<%= f.input :password_confirmation, label: "Confirme a password" %>
<%= f.input :nome %>
<%= f.input :foto, :label => "Foto" %>
<%= f.input :cod_postal, :label => "Código-Postal" %>
<%= f.input :localidade %>
<%= f.input :contacto1, :label => "Contactos" %>
<%= f.input :contacto2, label: false %>
<%= f.input :pagina, :label => "Página Pessoal" %>
<%= f.fields_for :candidato do |ff| %>
<%= ff.input :data_nascimento, :label => "Data de Nascimento" %>
<%= ff.input :bi, :label => "Bilhete de Identidade" %>
<%= ff.input :cv, :label => "Curriculum Vitae" %>
<%= ff.label :area_profissional, :label => "Área Profissional" %>
<%= ff.select :area_profissional, ["Programador_Web", "Programador_Java","Gestor"], :label => "Área Profissional" %>
<%= ff.input :apresentacao, :label => "Apresentação" %>
<%= ff.select :nivel_hab, ["Secundário","Licenciatura","Mestrado","Doutoramento"], :label => "Nível de Habilitações" %>
<%= ff.input :hab_literaria, :label => "Habilitações Literárias" %>
<%= ff.select :situacao_prof, ["Empregado","Desempregado"], :label => "Situação Profissional" %>
<%= ff.input :exp_profissional, :label => "Experiência Profissional" %>
<% end %>
<%= f.submit "Registar", class: "btn btn-large btn-primary" %>
<% end %>
And I can't create the damn User. It keeps rendering the new page. What the hell is wrong.
This is my Controller:
class UsersController < ApplicationController
def new
#user = User.new
if params[:param] == "candidato"
#role = "candidato"
##user.candidato = Candidato.new
#user.build_candidato
else
#role = "entidade"
##user.entidade = Entidade.new
#user.build_entidade
end
end
def create
#user = User.new(user_params)
if user_params[:role] == "candidato"
#user.build_candidato(user_params[:candidato_attributes])
##user.candidato = Candidato.new(user_params[:candidato_attributes])
if #user.save
#Sucesso
redirect_to root_path
else
#Falhou
#role = "candidato"
render 'new'
end
else
##user.entidade = Entidade.new(user_params[:entidade_attributes])
#user.build_entidade(user_params[:entidade_attributes])
if #user.save
#Sucesso
redirect_to root_path
else
#Falhou
#role = "entidade"
render 'new'
end
end
end
private
def user_params
params.require(:user).permit(:role,:email,:nome,:password,:password_confirmation,:pagina,:contacto1,:contacto2,:foto,:cod_postal,:localidade, :candidato_attributes => [:data_nascimento,:bi,:cv,:area_profissional,:apresentacao,:nivel_hab,:hab_literaria,:situacao_prof,:exp_profissional], :entidade_attributes => [:nip,:apresentacao,:atividade])
end
end
If someone knows what's wrong please tell me
Problem is here in your create method you are building dependent object twice and you have has_one relationship. You object for dependent model already created on new action on parent.
Your controller should look like :
def create
#user = User.new(user_params)
if #user.save
redirect_to root_path
else
#role = user_params[:role]
render 'new'
end
end
Form should look like :
<%= simple_form_for #user, :html => { :multipart => true } do |f| %>
<%= render 'shared/error_messages' %>
<%= f.input :email %>
<%= f.input :role, :as => :hidden, :input_html => { :value => #role } %>
<%= f.input :password %>
<%= f.input :password_confirmation, label: "Confirme a password" %>
<%= f.input :nome %>
<%= f.input :foto, :label => "Foto" %>
<%= f.input :cod_postal, :label => "Código-Postal" %>
<%= f.input :localidade %>
<%= f.input :contacto1, :label => "Contactos" %>
<%= f.input :contacto2, label: false %>
<%= f.input :pagina, :label => "Página Pessoal" %>
<% if #role == "candidato" %>
<%= f.fields_for :candidato do |ff| %>
<%= ff.input :data_nascimento, :label => "Data de Nascimento" %>
<%= ff.input :bi, :label => "Bilhete de Identidade" %>
<%= ff.input :cv, :label => "Curriculum Vitae" %>
<%= ff.label :area_profissional, :label => "Área Profissional" %>
<%= ff.select :area_profissional, ["Programador_Web", "Programador_Java","Gestor"], :label => "Área Profissional" %>
<%= ff.input :apresentacao, :label => "Apresentação" %>
<%= ff.select :nivel_hab, ["Secundário","Licenciatura","Mestrado","Doutoramento"], :label => "Nível de Habilitações" %>
<%= ff.input :hab_literaria, :label => "Habilitações Literárias" %>
<%= ff.select :situacao_prof, ["Empregado","Desempregado"], :label => "Situação Profissional" %>
<%= ff.input :exp_profissional, :label => "Experiência Profissional" %>
<% end %>
<%else%>
<%= f.fields_for :entidade do |ff| %>
<%= ff.input :atividade, :label => "atividade" %>
<%= ff.input :apresentacao, :label => "apresentacao" %>
<%= ff.input :nip, :label => "nip" %>
<% end %>
<% end %>
<%= f.submit "Registar", class: "btn btn-large btn-primary" %>
<% end %>
You also have to add :id and _destroy in attributes. It will used at the time of edit and delete child model.
def user_params
params.require(:user).permit(:role,:email,:nome,:password,:password_confirmation,:pagina,:contacto1,:contacto2,:foto,:cod_postal,:localidade, :candidato_attributes => [:id, :data_nascimento,:bi,:cv,:area_profissional,:apresentacao,:nivel_hab,:hab_literaria,:situacao_prof,:exp_profissional, :_destroy], :entidade_attributes => [:id, :nip,:apresentacao,:atividade, :_destroy])
end
#app/controllers/users_controller.rb
Class UsersController < ApplicationController
def new
#user = User.new
#user.send("build_#{params[:param]}")
end
def create
#user = User.new user_params
#user.save
end
private
def user_params
params.require(:user).permit(:role,:email,:nome,:password,:password_confirmation,:pagina,:contacto1,:contacto2,:foto,:cod_postal,:localidade, :candidato_attributes => [:data_nascimento,:bi,:cv,:area_profissional,:apresentacao,:nivel_hab,:hab_literaria,:situacao_prof,:exp_profissional], :entidade_attributes => [:nip,:apresentacao,:atividade])
end
end
When you pass nested attributes, you only need to build the initial associative object
In your create method, you're building the associative data again. A much better way will be to use the code above (albeit edited to represent your redirects), to create the User object
Validations aside, I don't see any reason why the above code wouldn't work with your form
I have form partial that allows the user to enter the subject and message that will be included in the outbound email. I want to allow the users to select the recipients of the email from the contacts that are associated with the invoice that the email belongs to. The email recipients that are selected through the nested form are to be stored in a separate table.
class EmailRecipient < ActiveRecord::Base
attr_accessible :contact_id, :email_id
belongs_to :email
end
class Email < ActiveRecord::Base
attr_accessible :subject, :message, :invoice_id, :email_recipients_attributes
belongs_to :invoice
has_many :email_recipients
accepts_nested_attributes_for :email_recipients
end
<%= simple_form_for [:invoice, #email], html: {class: "form-horizontal"} do |f| %>
<%= f.error_notification %>
<% #invoice.contacts do |c|%>
<%= f.fields_for :email_recipients do |builder| %>
<%= builder.input :contact_id, :as => :check_boxes %>
<%= c.name %><br/>
<% end %>
<% end %>
<%= f.input :subject, :as => "string" %>
<%= f.input :message, :input_html => { :class => 'span7', :rows => 10 } %>
<div class="form-actions">
<%= f.button :submit, "Send Invoice", :class => 'btn-warning' %>
<%= link_to 'Cancel', invoice_path(#invoice), :class => 'btn' %>
</div>
<% end %>
This isn't the prettiest answer, so I would love to see a better solution, but it gets the job done until my skills improve.
In the controller for the parent form I added:
#invoice.contacts.each { |c| #email.email_recipients.build(contact_id: c.id) }
This builds the records for all contacts whether they are needed or not. Then in the form partial I modified the nested form:
<%= simple_form_for [:invoice, #email], html: {class: "form-horizontal"} do |f| %>
<%= f.error_notification %>
<% count = 0 %>
<%= f.simple_fields_for :email_recipients do |email_recipients_form| %>
<%= email_recipients_form.input :_destroy, as: :boolean, :label => false do %>
<%= email_recipients_form.check_box :_destroy, {}, "false", "true" %>
<% contact = #invoice.contacts.find(#email.email_recipients[count].contact_id) %>
<%= contact.name + " (" + contact.email + ")" %>
<% end %>
<%= email_recipients_form.input :contact_id, as: :hidden %>
<% count += 1 %>
<% end %>
My validations are not working for a nested form - messages, which is in other models show page.
Here's the code:
Reserve Online:
<%= form_for([#trip, #trip.messages.build]) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.text_field :name, :class => "span3", :placeholder => "Name:" %>
<%= f.text_field :email, :class => "span3", :placeholder => "Email:" %>
<div class="h">
<%= f.text_field :subject, :class => "h", :value => (#trip.title) %>
</div>
<%= f.text_area :body, :class => "input-xlarge3", :placeholder => "Message:", :id => "textarea", :rows => "3" %>
<%= f.submit :class => " btn btn-primary btn-large ", :value => "Send Message" %>
<% end %>
</div>
Message.rb
class Message < ActiveRecord::Base
belongs_to :trip
attr_accessible :name, :email, :subject, :body
validates_presence_of :name
validates_format_of :email, :with => /^[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
validates_length_of :body, :maximum => 500
end
an the messages_controller.rb
class MessagesController < ApplicationController
def create
#trip = Trip.find(params[:trip_id])
#message = #trip.messages.create(params[:message])
if #trip.messages.create
MessageMailer.send_message(#message).deliver
redirect_to thank_you_path
else
redirect_to trip_path(#trip)
end
end
end
_error_messages.rb
<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-error">
The form contains <%= pluralize(object.errors.count, "error") %>.
</div>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li>* <%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
The whole code above works fine, but the validation part is simply ignored. And I don't see any errors.
So I Can't figure out what I'm doing wrong. Can You help?
Thank you!
I think there is a problem in your controller:
def create
#trip = Trip.find(params[:trip_id])
#message = #trip.messages.create(params[:message])
# the following line doesnt make sense
# you're recreating an empty message
# it should be something like "if #message.valid?"
if #trip.messages.create
MessageMailer.send_message(#message).deliver
redirect_to thank_you_path
else
redirect_to trip_path(#trip)
end
end
Try to fix that and see if it helps.
I am having problems with my ruby on rails app. I have two models - 'patient' and 'address', a patient has one address, and an address belongs to a patient.
Patient.rb
class Patient < ActiveRecord::Base
has_many :charge_slips
has_one :address
validates_presence_of :last_name
validates_presence_of :first_name
validates_presence_of :middle_name
end
Address.rb
class Address < ActiveRecord::Base
belongs_to :patient
validates_associated :patient
end
Patient-controller.rb
class PatientController < ApplicationController
def index
#title = "Outpatient Services - Patient"
#today = Date.today.to_formatted_s(:long)
#patients = Patient.find(:all)
end
def new
#patient = Patient.new
#address = Address.new
end
def create
#patient = Patient.new(params[:patient])
#patient.created_on = Date.today.to_formatted_s(:long)
if #patient.save
#address = Address.new(params[:address])
#address.patient_id = #patient.id
if #address.save
redirect_to :action => 'index'
else
redirect_to :action => 'new'
end
redirect_to :action => 'index'
else
redirect_to :action => 'new'
end
end
end
new.html.rb
<%= content_tag('h3', 'Create New Patient') %>
<hr>
<% form_for #patient, :url => { :action => "create" } do |patient_form| -%>
<%= error_messages_for :patient %>
<%= patient_form.label :last_name, 'Last Name:' %> <%= patient_form.text_field :last_name, :size => 30 %><br>
<%= patient_form.label :first_name, 'First Name:' %> <%= patient_form.text_field :first_name, :size => 30 %><br>
<%= patient_form.label :middle_name, 'Middle Name:' %> <%= patient_form.text_field :middle_name, :size => 30 %><br>
<fieldset>
<legend>Patient's Permanent Address</legend>
<%= error_messages_for :address %>
<% patient_form.fields_for #address do |address_fields| -%>
<%= address_fields.label :street_name, 'Street Name:' %> <%= address_fields.text_field :street_name %><br>
<%= address_fields.label :barangay, 'Barangay:' %> <%= address_fields.text_field :barangay %><br>
<%= address_fields.label :city_municipality, 'City/Municipality:' %> <%= address_fields.text_field :city_municipality %><br>
<%= address_fields.label :country, 'Country:' %> <%= address_fields.text_field :country %><br>
<%= address_fields.label :zip_cide, 'Zip Code:' %> <%= address_fields.text_field :zip_code %><br>
<% end -%>
</fieldset>
<%= submit_tag "Add Patient" %>
<% end -%>
Everytime I add a new patient an error is thrown. Here is a part of the error:
ActiveRecord::AssociationTypeMismatch in PatientController#create
Address(#31360520) expected, got HashWithIndifferentAccess(#23815500)
RAILS_ROOT: C:/www/Outpatient Application Trace | Framework Trace | Full Trace
C:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations/association_proxy.rb:263:in `raise_on_type_mismatch'
C:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations/has_one_association.rb:52:in `replace'
C:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/associations.rb:1246:in `address='
C:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2740:in `send'
C:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2740:in `attributes='
C:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2736:in `each'
C:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2736:in `attributes='
C:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.3/lib/active_record/base.rb:2434:in `initialize'
C:/www/Outpatient/app/controllers/patient_controller.rb:14:in `new'
C:/www/Outpatient/app/controllers/patient_controller.rb:14:in `create'
I am new to RoR and would like to learn the language through practice. I want to know what might be wrong with the code. Thanks!
First your Patient model needs an accepts_nested_attributes_for
class Patient < ActiveRecord::Base
has_many :charge_slips
has_one :address
validates_presence_of :last_name
validates_presence_of :first_name
validates_presence_of :middle_name
accepts_nested_attributes_for :address
end
Your controller can be simplified a great deal. There is no need to save the address separately since #patient.save will take care of that. You don't need to set
the created_on attribute manually since it will be set automagically :) Also when #patient.save fails you probably want to render :action => 'new' and not redirect_to :action => 'new'. This will redisplay the form with any validation errors (redirect_to will not.)
Also note that i renamed your controller class to PatientsController instead of PatientController. This will be more in line with Rails' RESTful conventions and will also help you simplify your view a bit. If you do this you'll need a map.resources :patients in your routes.db file, and you'll need to rename your files too.
class PatientsController < ApplicationController
def index
#title = "Outpatient Services - Patient"
#today = Date.today.to_formatted_s(:long)
#patients = Patient.find(:all)
end
def new
#patient = Patient.new
#patient.build_address
end
def create
#patient = Patient.new(params[:patient])
if #patient.save
redirect_to :action => 'index'
else
render :action => 'new'
end
end
end
Your view has a small error. It needs to be fields_for :address and not fields_for #address. Also since your controller is now RESTful your can remove the :url => { :action => "create" } part.
<%= content_tag('h3', 'Create New Patient') %>
<hr>
<% form_for #patient do |patient_form| -%>
<%= error_messages_for :patient %>
<%= patient_form.label :last_name, 'Last Name:' %> <%= patient_form.text_field :last_name, :size => 30 %><br>
<%= patient_form.label :first_name, 'First Name:' %> <%= patient_form.text_field :first_name, :size => 30 %><br>
<%= patient_form.label :middle_name, 'Middle Name:' %> <%= patient_form.text_field :middle_name, :size => 30 %><br>
<fieldset>
<legend>Patient's Permanent Address</legend>
<%= error_messages_for :address %>
<% patient_form.fields_for :address do |address_fields| -%>
<%= address_fields.label :street_name, 'Street Name:' %> <%= address_fields.text_field :street_name %><br>
<%= address_fields.label :barangay, 'Barangay:' %> <%= address_fields.text_field :barangay %><br>
<%= address_fields.label :city_municipality, 'City/Municipality:' %> <%= address_fields.text_field :city_municipality %><br>
<%= address_fields.label :country, 'Country:' %> <%= address_fields.text_field :country %><br>
<%= address_fields.label :zip_cide, 'Zip Code:' %> <%= address_fields.text_field :zip_code %><br>
<% end -%>
</fieldset>
<%= submit_tag "Add Patient" %>
<% end -%>
Hope this helps :)