Im currently working in an Rails 5 application where you can search for a first name or last name and records of the customers of that account would be displayed. However I am getting a Nil object return from search algorithm.
customers_controller:
class CustomersController < ApplicationController
def index
if params[:keywords].present?
#keywords = params[:keywords]
customer_search_term = CustomerSearchTerm.new(#keywords)
#customer = Customer.where(
customer_search_term.where_clause,
customer_search_term.where_args).
order(customer_search_term.order)
else
#customers = []
end
end
end
As you can see if there is no records found is suppose to return an empty array but is returning a Nil object.
customers/index.html.erb
[![<header>
<h1 class="h2">Customer Search</h1>
</header>
<section class="search-form">
<%= form_for :customers, method: :get do |f| %>
<div class="input-group input-group-lg">
<%= label_tag :keywords, nil, class: "sr-only" %>
<%= text_field_tag :keywords, nil,
placeholder: "First Name, Last Name or Email Address",
class: "form-control input-lg" %>
<span class="input-group-btn">
<%= submit_tag "Find Customers", class: "btn btn-primary btn-lg" %>
</span>
</div>
<% end %>
</section>
<section class="search-results">
<header>
<h1 class="h3">Results</h1>
</header>
<table class="table table-striped">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Joined</th>
</tr>
</thead>
<tbody>
<% #customers.each do |customer| %>
<tr>
<td><%= customer.first_name %></td>
<td><%= customer.last_name %></td>
<td><%= customer.email %></td>
<td><%= l customer.created_at.to_date %></td>
</tr>
<% end %>
</tbody>
</table>
</section>][1]][1]
The first thing you should understand is that instance variables return nil if they haven't been set. If you say #fake_var == nil it will be true if you never defined #fake_var before this. You can contrast this with regular local variables, which will raise a NoMethodError if you try and use them before they're defined. For example, puts(fake_var) will raise a NoMethodError for fake_var.
Now look at your template. No matter what it will loop over #customers. If #customers has not been set, you'll see a NoMethodError because you can't call each on nil.
Finally, look at your controller action:
def index
if params[:keywords].present?
#keywords = params[:keywords]
customer_search_term = CustomerSearchTerm.new(#keywords)
#customer = Customer.where(
customer_search_term.where_clause,
customer_search_term.where_args).
order(customer_search_term.order)
else
#customers = []
end
end
Specifically the case when params[:keywords].present?. You never set #customers in this case so it will be nil when the template tries to access it.
I think if you simply replaced #customer = with #customers = it would solve your problem.
you can force it to return array using #to_a which converts nil to empty array
def index
return [] unless params[:keywords]
#keywords = params[:keywords]
customer_search_term = CustomerSearchTerm.new(#keywords)
#customer = Customer.where(
customer_search_term.where_clause,
customer_search_term.where_args).
order(customer_search_term.order
).to_a
end
https://apidock.com/ruby/Array/to_a
Related
I'm putting together a combo box or called the same as a select in rails, I put everything together but it gives me an error that tells me that I have a problem with the map inside the select, I'm using simple_form_for and I'm doing a map inside the collection inside the selector or called in simple_for associatio.
I copy the view and the controller
This view
<h1>HistContact#index</h1>
<p>Find me in app/views/hist_contact/index.html.erb</p>
<%= simple_form_for #histcontact, url:hist_contact_index_path do |f| %>
<% f.association :contact, collection: #contacts.map{|cont| [cont.name , cont.id]}%>
<%f.submit "buscar"%>
<% end %>
<table id = "client_table" class="table table-striped table-sm">
<thead>
<tr>
<th>Id</th>
<th>fecha</th
</tr>
</thead>
<tbody>
<% #histcontacts.each do |c|%>
<tr>
<td> <%= c.id %> </td>
<td> <%= c.created_at %></td>
</tr>
<% end %>
</tbody>
</table>
the controller
class HistContactController < ApplicationController
before_action :authenticate_user!
def index
#histcontacts = HistContact.all
#contacts = Contact.all
end
def new
#histcontact = HistContact.new
#contacts = Contact.new
end
def create
#histcontact = HistContact.find(contact_id: params[:contact])
end
private
def contactID(current_user)
client_id = Client.where(user_id: current_user.id)
contact_id = Contact.where(client_id: client_id.ids[0])
return contact_id
end
end
Thank you
According to error, you are trying to map a single object instead of an array of objects. Based on your controller code, the view file you shared is probably new.html.erb. To solve this problem you need do it like this:
def new
#histcontact = HistContact.new
#contacts = Contact.all
end
Currently unable to pass information from the cycles controller to the cycle_nominees_table.html.erb using partials.
The data is defined in my controller show method.
And the show method has information in the #nominations_data and #nominations_team_data.
Why cant my _cycles_nominations_table.html.erb access nominations_data thats being passed into the partial?
Ive been using this link for direction.
Code Below:
app/controllers/cycles_controller.rb
def show
...
#nominations_data = {}
#nominations.each do |nomination|
#nominations_data[nomination.for_user_id] ||= {}
#nominations_data[nomination.for_user_id][:nominee] ||= nomination.for_user
if user_is_admin
#nominations_data[nomination.for_user_id][:nominations] ||= []
#nominations_data[nomination.for_user_id][:nominations].push nomination
end
if user_is_admin_or_reviewer
#nominations_data[nomination.for_user_id][:count] ||= 0
#nominations_data[nomination.for_user_id][:count] += 1
end
end
#nominations_data = #nominations_data.sort_by { |_nid, nomination| nomination[:nominee].name }
#nominations_team_data = {}
#team_nominations.each do |nomination|
#nominations_team_data[nomination.for_user_id] ||= {}
#nominations_team_data[nomination.for_user_id][:nominee] ||= nomination.for_user
if user_is_admin
#nominations_team_data[nomination.for_user_id][:nominations] ||= []
#nominations_team_data[nomination.for_user_id][:nominations].push nomination
end
if user_is_admin_or_reviewer
#nominations_team_data[nomination.for_user_id][:count] ||= 0
#nominations_team_data[nomination.for_user_id][:count] += 1
end
end
#nominations_team_data = #nominations_team_data.sort_by { |_nid, nomination| nomination[:nominee].name }
end
app/views/cycles/show.html.erb
<div class="container-float-right-small" id="cycle-nominees-section">
<h2 class="inline">Nominees for <%= #cycle.name %></h2>
<h4 class="inline"> - (<%= #cycle.votes_per_reviewer %> votes allowed)</h4>
<h5> Indivdual Nominees: </h5>
<!-- <%= render "cycles/cycle_nominees_table" %>-->
<%= render partial: "cycles/cycle_nominees_table", locals: { nominations_data: #nominations_data } %>
<h5> Team Nominees: </h5>
<!-- <%= render "cycles/cycle_nominees_table" %>-->
<%= render partial: "cycles/cycle_nominees_table", locals: { nominations_data: #nominations_team_data } %>
</div>
app/views/cycles/_cycle_nominees_table.html.erb
<% if nominations_data.empty? %>
<th class="center" colspan="4"><h3>There are no nominees <%= "for cycle '#{#cycle.name}'" if #cycle %></th>
<% end %>
</thead>
<tbody>
<% nominations_data.each do |nid, data| %>
<tr id='<%= "nominee-row-#{nid}" %>' class="nominee-row">
<% if user_is_reviewer && #cycle.voting_open %>
<td class="center">
<% nomination_icon_class = "voted_for" if Vote.where(cycle_id: #cycle.id, by_user_id: current_user.id, for_user_id: data[:nominee].id).count > 0 %>
<span class="glyphicon glyphicon-check pointer <%= nomination_icon_class %>" id=<%= "vote_for_nominee_#{nid}" %> onclick="<%= "Vote.send_vote_data(this, #{data[:nominee].id}, #{#cycle.id})" %>"></span>
</td>
<% end %>
For my final project I need to create two radio buttons with a submit button that will display my GPA for all my classes and those in my major. I can have them displayed easily but am stuck when I need to use radio buttons to display only one
<h2>Please select which GPA you would like to view:</h2>
<%= form_tag("/trans/transcript", :method => "get") do %>
<table>
<tr>
<th>Major Credits</th>
<th>All Credits</th>
</tr>
<tr>
<td><%= radio_button_tag(:gpa, "Major") %></td>
<td><%= radio_button_tag(:gpa, "All") %> </td>
</tr>
</table>
<%= submit_tag("View GPA") %>
<% end %>
<p> Major credits GPA <%= #transcript.GPA_for_major %>
<p> All credits GPA <%= #transcript.GPA_for_non_major %>
Everything appears fine but I'm not sure how to set up the controller to say if he clicks the major gpa radio button and clicks "View GPA" this <%= #transcript.GPA_for_major %> should display
SHORT ANSWER
Make an instance variable #gpa in TransController's transcript action
In the transcript action, check for params[:gpa]
set #gpa & #transcript to nil if params[:gpa].nil?
set #gpa to params[:gpa] and #transcript accordingly if params[:gpa] is not nil
In the view/trans/transcript.html.erb
If #gpa is nil, display nothing
If #gpa == "Major" show #transcript.GPA_for_major
If #gpa == "All" show #transcript.GPA_for_non_major
LONG ANSWER
Assuming that the controller is trans and the action is transcript, here is what you should do in TransController
class TransController < ApplicationController
def transcript
if params[:gpa].nil?
#transcript = #gpa = nil
else
#gpa = params[:gpa]
#transcript = ... # Find your transcript here
end
end
# ... other actions
# ... other actions
# ... other actions
end
and here is how the trans/transcript.html.erb view should look like -
<h2>Please select which GPA you would like to view:</h2>
<%= form_tag('trans/transcript', :method => "get") do %>
<table>
<tr>
<th>Major Credits</th>
<th>All Credits</th>
</tr>
<tr>
<td>Major<%= radio_button_tag(:gpa, "Major") %></td>
<td>All<%= radio_button_tag(:gpa, "All") %> </td>
</tr>
</table>
<%= submit_tag("View GPA") %>
<% end %>
<% if #gpa == "Major" %>
<%= #transcript.GPA_for_major %>
<% elsif #gpa == "All" %>
<%= #transcript.GPA_for_major %>
<% end %>
I'm pretty new to Ruby on Rails and Ruby in general but I'm trying to make a small website with simple database in Ruby on Rails.
At the moment I have the html.erb pages to show, add and edit records.
The next thing i wanted to do is the action that redirects user to a page with more info about the record he clicked in the record table.
I can't really think of any way to do this.
Any help would be really appriciated.
p.s. Sorry for any mistakes in my English - it's not my first language and im still learning!
Here is my html code:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="tablecontainer">
<table class="table table-bordered table-condensed">
<tr class="success">
<td><b>Nazwa</b></td>
<td><b>Obrażenia</b></td>
<td><b>Typ</b></td>
<td><b>Waga</b></td>
<td><b>Zasięg</b></td>
<td><b>Szybkość</b></td>
<td><b>Rzadkość</b></td>
<td><b>Opcje</b></td>
</tr>
<% #biala.each do |b| %>
<tr>
<td><%= b.nazwa %></td>
<td><%= b.obrazenia %>%</td>
<td><%= b.typ %></td>
<td><%= b.waga %></td>
<td><%= b.zasieg %></td>
<td><%= b.szybkosc %></td>
<td><%= b.rzadkosc %></td>
<td><%= link_to '', {id: b.id, action: 'db_wiecejbiala'}, class: "glyphicon glyphicon-info-sign" %><%= link_to '', {id: b.id, action: 'db_edytujbiala'}, class: "glyphicon glyphicon-pencil" %> <%= link_to '', {id: b.id, action: 'usunbiala'}, data: {confirm: 'Jesteś tego pewien?'}, class: "glyphicon glyphicon-remove" %></td>
</tr>
<% end %>
</table>
And here is the controller:
class BazaController < ApplicationController
def db_bronbiala
#biala = BronBiala.all
#iloscbiala = BronBiala.count
end
def db_dodajbiala
#nowybiala = BronBiala.new
end
def utworzbiala
#nowybiala = BronBiala.new(parametrybiala)
if #nowybiala.save
redirect_to(action: 'db_bronbiala')
else
render('db_dodajbiala')
end
end
def parametrybiala
params.require(:bron_biala).permit(:nazwa, :obrazenia, :typ, :waga, :zasieg, :szybkosc, :rzadkosc, :zalety, :wady, :ciekawostki, :opis)
end
def usunbiala
usuwaniebiala = BronBiala.find(params[:id]).destroy
#biala = BronBiala.all
render('db_bronbiala')
end
def db_edytujbiala
#biala = BronBiala.all
#edytowanabiala = BronBiala.find(params[:id])
end
def aktualizujbiala
#biala = BronBiala.all
#edytowanabiala = BronBiala.find(params[:id])
if #edytowanabiala.update_attributes(parametrybiala)
redirect_to(action: 'db_bronbiala')
else
render('db_edytujbiala')
end
end
def db_wiecejbiala
#biala = BronBiala.all
#bialawiecej = BronBiala.find(params[:id])
end
end
And the db_bialawiecej code:
<div class="content">
<h2>Lista:</h2>
<div class="tablecontainer">
<table class="table table-bordered table-condensed">
<tr class="success">
<td><b>Nazwa</b></td>
<td><b>Obrażenia</b></td>
<td><b>Typ</b></td>
<td><b>Waga</b></td>
<td><b>Zasięg</b></td>
<td><b>Szybkość</b></td>
<td><b>Rzadkość</b></td>
</tr>
<% #bialawiecej.id do |b| %>
<tr>
<td><%= b.nazwa %></td>
<td><%= b.obrazenia %>%</td>
<td><%= b.typ %></td>
<td><%= b.waga %></td>
<td><%= b.zasieg %></td>
<td><%= b.szybkosc %></td>
<td><%= b.rzadkosc %></td>
</tr>
<% end %>
</div>
</div>
On click send id of clicked item (GET). you will have link similar to : localhost:3000/desired_model/5
then in action do #desired_model = DesiredModel.find(params[:id])
redirect user to desired show page.
Show data.
Next time please provide some code :)
I have following <tr> tag in my table
<% if user.company.nil? %>
<tr class="error">
<% else %>
<tr>
<% end %>
<td><%= user.name %></td>
</tr>
I would like to add another if statement
<% if user.disabled? %>
<tr class="disabled">
<% end %>
So when two of this statements are true I would like to receive:
<tr class="error disabled">
I know I should move that to helper but how to write good case statment for extending class depends of this statements?
def tr_classes(user)
classes = []
classes << "error" if user.company.nil?
classes << "disabled" if user.disabled?
if classes.any?
" class=\"#{classes.join(" ")}\""
end
end
<tr<%= tr_classes(user) %>>
<td><%= user.name %></td>
</tr>
But the good style is:
def tr_classes(user)
classes = []
classes << "error" if user.company.nil?
classes << "disabled" if user.disabled?
if classes.any? # method return nil unless
classes.join(" ")
end
end
<%= content_tag :tr, :class => tr_classes(user) do -%> # if tr_classes.nil? blank <tr>
<td><%= user.name %></td>
<% end -%>
you could try a helper method, something like
def user_table_row(user)
css = ""
css = "#{css} error" if user.company.nil?
css = "#{css} disabled" if user.disabled?
content_tag :tr, class: css
end
not sure how well this will work in the case of a table row, as you will want to nest td inside it
UPDATE: here is updated version yielding the block of td code
def user_table_row(user)
css = # derive css, using string or array join style
options = {}
options[:class] = css if css.length > 0
content_tag :tr, options do
yield
end
end
then in the view
<%= user_table_row(user) do %>
<td><%= user.name %></td>
<% end %>