undefined method `each' for nil:NilClass for order method - ruby-on-rails

I get this error when I try to run my code. From what I've researched my problem is either in my controller or my view
This is my controller
class AppointmentsController < ApplicationController
def index
#appointments = Appointment.order('appt_time ASC')
#appointment = Appointment.new
end
end
This is my view
%h1 React Calendar
%h2 Appointments
%h3 Make a new appointment
= form_for #appointment do |f|
= f.text_field :title
= f.text_field :appt_time
= f.submit 'Make appointment'
= #appointmets.each do |a|
%h3 = a.title
%p = a.appt_time
I'm running
Rails 5.1.3
Ruby 2.4.1

Undefined method <method name> for nil:NilClass means you are calling that method, in this case .each, on something that does not exist (Nil).
In this case it is just because you have a typo in your view so the variable is not there like you think it is.
= #appointmets.each do |a|
%h3 = a.title
%p = a.appt_time
needs to be
= #appointments.each do |a| <--- you missed the "n"
%h3 = a.title
%p = a.appt_time

Related

ActiveRecord::StatementInvalid in Show Controller

I've got a simple search form, in rails 4 app, that needs two params passed to be able to show relevant data.
I'm getting an 'Mysql2::Error: Unknown column 'data inputted' but the columns do exist. If I instead of '#search = Page.where(params[:one] && params[:two])' use '#search = Page.all' the data shows, but all of it shows.
Form
<%= form_tag(page_show_path, id: "search-form") do %>
<%= text_field_tag :one, params[:one], placeholder: "One" %>
<%= text_field_tag :two, params[:two], placeholder: "Two" %>
<%= submit_tag "Search", :name => nil %>
<% end %>
Model
def self.one(query)
where("one = ?", "%#{query}%")
end
def self.two(query)
where("two = ?", "%#{query}%")
end
Controller
def show
if (params[:one] && params[:two]).present?
#search = Page.where(params[:one] && params[:two])
else
redirect_to page_path, notice: "Not a valid combination"
end
end
You can Create and Use Scope.
scope :find_one_two, ->(query_one, query_two) { where("one = ? AND two = ? ", query_one, query_two) }
#search = Page.find_one_two(params[:one], params[:two])
OR
You can use.
#search = Page.where("one = ? AND two = ?", params[:one], params[:two])
def show
if (params[:one] && params[:two]).present?
#search = Page.where("one like ? AND two like ? ", "%#{params[:one]}%", "%#{params[:two]}%")
else
redirect_to page_path, notice: "Not a valid combination"
end
end
This may solve your problem.

Passing params without nil

I want to pass the value of a form to a Controller that should call a method from the Model for searching products.
I want to pass the category_id and the string that the user writes at the textfield.
I would pass to the model even the blank value of params (if the user doesn't write something on the search bar or choose none category)
I want to save even the blank value cause in the model, the SQL blank variable take "all" things.
And this is good a cause if there is something in the params , the SQL will find that thing, BUT if there is nothing in the params, the SQL will take all products.
I'm not able to save the value of params in varibiles cause if params is blank it returns to me this error:
undefined method `[]' for nil:NilClass
I hope you understand me and what I want to do.
In other words , I want to use a simple assignment to pass a value (even blank values) to a model to do a SQL query. In one shoot of code I want to program two cases.
Here my code.
In my Controller:
...
if params[:search]
#search_name = params[:search]
end
if params[:category][:name]
#category = params[:category][:name]
end
#products = Product.search(#search_name,#category)
...
In my Model:
def self.search(search_name,category)
ricerca = Product.where("category_id = ? ",category)
ricerca = ricerca.where("title like ? ", "%#{search_name}%")
end
You can get category parameters by defining a method like,
def category_params
params.fetch(:category, {})
end
And, then look up for Products by,
#search_name = params[:search]
#category = category_params[:name]
#products = Product.search(#search_name, #category)
In my opinion, if you are making a direct query on Product, then you should do like,
def product_params
params.fetch(:product, {})
end
#category = product_params[:category_id]
#title = product_params[:title]
#products = Product.search(#category, #title)
And in product model,
def self.search(category, title)
where("category_id = ? AND title LIKE ?", category, "%#{title}%")
end
Try this:
#search_name = params[:search]
#category = (params[:category].blank? ? nil : params[:category][:name])
#products = Product.search(#search_name,#category)
#Vito, change the line -> #category = params[:category][:name] in your controller by
#category = params[:category].present? ? params[:category][:name]
the issue is when you don't select the category then params[:category] comes nil and you are fetching name from params[:category] that's why error "undefined method `[]' for nil:NilClass" is comming.
Hope this will resolve your problem.
i still have problems , cause when i wrote
if params[:category]
#category = params[:category][:name]
else
#category = " "
end
if params[:search]
#nome_ricerca = params[:search]
else
#nome_ricerca = " "
end
#products = Product.search(#nome_ricerca,#category)
i have this problem:
Showing C:/Bitnami/depot/app/views/store/index.html.erb where line #18 raised:
undefined method `name' for "":String
Extracted source (around line #18):
<p>
<%= label_tag :search, 'Search:' %>
<%= text_field_tag :search, params[:search] %>
<%= collection_select :category, :name, Category.all, :id, :name, {:prompt => 'All Categories'} %>
<%= submit_tag "Search", name: nil %>
</p>
what is this?
Ok, i fixed the problem
it was (i think) concerning the fact that i used #category as variable name
maybe the view gets in confusion for this
i call #category in #cat and the problem disappears
But , now the problem is that the SQL query doesn't return all the category if i pass "" in the variable #cat
How can i have all the result of a query? with like %% it works but with
category_id = "" no. why?
I post the code fixed for others:
In Controller:
if params[:category]
#cat = params[:category][:name]
else
#cat = ''
end
if params[:search]
#nome_ricerca = params[:search]
else
#nome_ricerca = ''
end
#products = Product.search(#nome_ricerca,#cat)
In model:
def self.search(nome_ricerca,categoria)
ricerca = Product.where("title like ? AND category_id = ? ", "%#{nome_ricerca}%",categoria)
end
LAST POST:
PROBLEM FIXED:
In Controller
#stringa_sql = ""
if params[:search]
#nome_ricerca = params[:search]
else
#nome_ricerca = ''
end
#stringa_sql = "title like "+"'%"+#nome_ricerca+"%'"
if params[:category]
if params[:category][:name] != ""
#cat = params[:category][:name]
#stringa_sql += " AND category_id = "+#cat
else
#cat = ''
end
end
#products = Product.search(#stringa_sql)
In Model:
def self.search(stringa_sql)
ricerca = Product.where(stringa_sql)
end
Question: does this solution suffer Sql Injection ?
Thx all :)
I Hope this solution will help someone.

Submitting multiple records using AJAX

I do not have much idea on jQuery/Ajax. Could someone help me to submit the forms dynamically
here is the requirement:
- I have set of tests
- Each test has a result
- Each test result stored as separate record
I am thinking of following approach:
- display each test result as a separate form and submit each one of them using AJAX
I hope there would be a better approach, please help me
here are my code:
//results controller
class ResultsController < ApplicationController
def index
#results = Result.all
#tests = Tests.all
end
def new
#result = Result.new
end
//view
#tests.each do |test|
= form_for(#result) do |r|
= r.label :test_id, test.name
= r.hidden_field :test_id, :value => test_id
= r.select :status, options_for_select(%w[UNTESTED PASS FAIL PENDING BLOCKED INVALID])
= r.submit "Submit"
The index action from controller will call index page
In index page
= #tests.each do |test|
#test.#{test.id}= render partial: "test", :locals => {test: test}
create one _test.html page In _test page do all this,
= form_for(test) do |test|
= r.label :test_id, test.name
= r.hidden_field :test_id, :value => test_id
= r.select :status, options_for_select(%w[UNTESTED PASS FAIL PENDING BLOCKED INVALID])
= r.submit "Submit"
create one index.js.html file
:plain
$("#test_#{#test.id}").html("#{escape_javascript(render(:partial => "test", :locals => { :test => #test}))}");

Rails 4 Cannot access hash in nested form (undefined method `[]' for nil:NilClass)

I've build quite complex form which creates one prescription with many realtions. I am using this syntax in view:
- provide(:title, 'Create prescription')
%h1 Add medicines to prescription
.row
.span6.offset3
= form_for #prescription do |f|
= render 'shared/error_prescription_messages'
%p
= f.hidden_field :patient_id, :value => params[:patient_id]
= f.hidden_field :user_id, :value => current_user.id
= f.fields_for :relations do |builder|
= render 'child_form', :f => builder
%p= f.submit "Submit"
chlid_form is quite simple :
- it=f.options[:child_index].to_i
- n= it.to_s
%h2
= "Medicine ##{it+1}"
= f.hidden_field :medicine_id, :id => "my_medicine_id#{it}"
- if params[:prescription].nil? || params[:prescription][:relations_attributes][n.to_sym][:medicine_name].nil?
= f.autocomplete_field :medicine_name, autocomplete_medicine_name_relations_path, :id_element => "#my_medicine_id#{it}"
- else
= f.autocomplete_field :medicine_name, autocomplete_medicine_name_relations_path, :id_element => "#my_medicine_id#{it}", :value => params[:prescription][:relations_attributes][n.to_sym][:medicine_name]
= f.label :amount, "Amount of medicine boxes"
= f.number_field :amount, :value => 1
= f.label :daily
= f.number_field :daily, :value => 1
= f.label :period_in_days, "Duration of treatment (in days)"
= f.number_field :period_in_days, :value => 1
So as you can see I'm using f.options[:child_index] to get index of child (0,1,2...) cause I generate multiple items with this particular form. I then put it to variable it and sucessfully use it in :id_element => "#my_medicine_id#{it}" which works PERFECTLY fine (creates my_medicine_id0, my_medicine_id1 ....) Although it doesn't work in this line:
:value => params[:prescription][:relations_attributes][n.to_sym][:medicine_name]
where n is just n=it.to_s.
I though somethings wrong in controller but if I change this line to whatever
:value => params[:prescription][:relations_attributes]**[:'0']**[:medicine_name] or any other integer from 0 to 4 everything works great, but I NEED dynamic change in this one. So I got proof that it DOES work because it generates integer fine here "#my_medicine_id#{it}" but won't work in hash! And when I print the whole hash from params I get this:
{"patient_id"=>"7", "user_id"=>"1", "relations_attributes"=>{"0"=>{"medicine_id"=>"13490", "medicine_name"=>"Locacid 500 mcg/g (0,05%) (1 tuba 30 g)", "amount"=>"0", "daily"=>"1", "period_in_days"=>"1"}, "1"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}, "2"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}, "3"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}, "4"=>{"medicine_id"=>"", "medicine_name"=>"", "amount"=>"1", "daily"=>"1", "period_in_days"=>"1"}}}
so to get the values I need it's pretty obvious that
params[:prescription][:relations_attributes][SOME_KIND_OF_INETEGER][:medicine_name] should work, but doesn't.
Controller code:
class PrescriptionsController < ApplicationController
before_action :signed_in_user
before_action :doctor_user, only: [:new, :create]
before_action :pharmacist_user, only: [:update]
def new
#prescription =Prescription.new
5.times { #prescription.relations.build }
end
def create
#prescription = Prescription.new(new_prescription_params)
if #prescription.save
flash[:success] = "Prescription created."
redirect_to #prescription
else
5.times { #prescription.relations.build }
render 'new', :prescription => params[:prescription]
end
end
def show
#prescription = Prescription.find(params[:id])
#medicines = #prescription.medicines.paginate(page: params[:page], :per_page => 10)
end
def update
#prescription = Prescription.find(params[:id])
#patient = Patient.find(params[:patient_id])
if !prescription_expired?(#prescription)
#prescription.realized = 1
if #prescription.save
flash[:success] = "Prescription realized."
redirect_to #patient
else
redirect_to root_url
end
else
flash[:notice] = "Can't realize, prescription expired."
redirect_to #patient
end
end
private
def new_prescription_params
params.require(:prescription).
permit(:patient_id, :user_id, relations_attributes: [:medicine_id, :medicine_name, :amount, :daily, :period_in_days])
end
def doctor_user
redirect_to(root_url) unless current_user.function == "doctor"
end
def pharmacist_user
redirect_to(root_url) unless current_user.function == "pharmacist"
end
def prescription_expired?(presc)
presc.created_at < 1.month.ago
end
def signed_in_user
unless signed_in?
store_location
flash[:notice] = "Please log in."
redirect_to login_url
end
end
end
I run out of ideas so I ask you guys if anyone can help. Thanks.
There is no point in using params in your view since you already assigned those to your models. Also when you rendering your new action, those params doesn't exist as nothing has been send to the server yet. Just get rid of all the values from inputs.
Your partial should look like:
- it=f.options[:child_index].to_i
- n= it.to_s
%h2
= "Medicine ##{it+1}"
= f.hidden_field :medicine_id, :id => "my_medicine_id#{it}"
= f.autocomplete_field :medicine_name, autocomplete_medicine_name_relations_path
= f.label :amount, "Amount of medicine boxes"
= f.number_field :amount
= f.label :daily
= f.number_field :daily
= f.label :period_in_days, "Duration of treatment (in days)"
= f.number_field :period_in_days
If you want your fields to have default value, set default value inside your database.

Rails update_attribute not found

i need update a single record attribute but i canĀ“t. alumno_id is foreign key of model 'alumno'. the code show the records and if submit 'Aceptar' in one record, need a change the attribute estado to 1
in Model
class Postulacion < ActiveRecord::Base
attr_accessible :ramo, :estado, :alumno_id
belongs_to :alumno
end
in View
<h1>Lista de Postulaciones</h1>
<% #postulaciones.each do |p| %>
<% #id = p.id %>
<%= #id %>
<p>
<td><%= Alumno.find(p.alumno_id).full_name%></td>
<td><%='=> '+ p.ramo %></td>
<td><% if p.estado == 0 %>
<%= 'Pendiente =>' %>
<%= form_tag :action => 'aceptar' do %>
<%= submit_tag 'Aceptar' %></p>
<%end%>
<%else%>
<%='=> Aceptado' %>
<%end%>
</td>
</p>
<% end %>
in controller
class ListadoController < ApplicationController
def listar
#postulaciones = Postulacion.all
respond_to do |format|
format.html
format.json { render json: #postulaciones }
end
end
def aceptar
#postulacion = Postulacion.where(id: #id).first #Edit
#postulacion.estado = 1 #Edit
#postulacion.save #Edit
redirect_to "/"
end
end
Error "undefined method `update_attribute' for []:ActiveRecord::Relation"
Thanks
With this code:
#postulacion = Postulacion.where(alumno_id: #id )
You are declaring #postulacion as a collection, not as a single instance. You can fix this by calling .first:
#postulacion = Postulacion.where(alumno_id: #id ).first
Or by using find_by instead of where:
#postulacion = Postulacion.find_by(alumno_id: #id )
One other thing - this code isn't checking for the possibility that the Postulacion instance might not exist. You should add some logic to handle this...
Your #postulacion variable holds ActiveRecord::Relation instead of single ActiveRecord object. Try:
def acceptar
#postulacion = Postulacion.find_by_alumino_id(#id)
# ...
end
or, if you'd be using Rails 4:
#postulacion = Postulacion.find_by(alumino_id: #id)

Resources