How to render an array in Rails - ruby-on-rails

In my Rails application, I have a class Bar and a controller FooController.
class Bar
attr_accessor :id
end
class FooController < ApplicationController
def index
#rows = {}
bar = Bar.new
bar.id = 1
#rows[0] = bar
render "index"
end
end
In the view, I would like to render like this
<table>
<% #rows.each do |bar| %>
<tr>
<td><%= bar.id %></td>
</tr>
<% end %>
</table>
But it will throws error
undefined method `id' for [0, #<Bar:0x00007fc65db33320 #id=1>]:Array
If I render like this:
<%= #rows %>
the raw data of the array #rows will be rendered as:
{0=>#<Bar:0x00007fc65db33320 #id="1">}
How do I render the elements one by one?

The problem is that #rows = {} doesn't assign an array but a hash. And therefore #rows[0] = bar doesn't store bar as the first element in the array, but it stores bar under the key in the hash.
Just change your controller method to:
def index
#rows = []
bar = Bar.new
bar.id = 1
#rows << bar
render "index"
end

Related

I have two models (events & artists) pagy is working fine with my artist model, but my event model isn't displaying last records

I do have a more elaborate index method in my events controller
def index
if params[:q]
params[:q][:combinator] = "and"
params[:q][:groupings] = []
split_geo = params[:q][:address_or_city_or_state_or_country_or_continent_cont_all].split((/(,\s*)+/))
split_geo.map! do |a|
I18n.transliterate a
end
split_geo.each_with_index do |word, index|
params[:q][:groupings][index] = { address_or_city_or_state_or_country_or_continent_cont_all: word }
end
end
#q = Event.ransack(params[:q])
#pagy, #events = pagy(#q.result(distinct: true))
end
In my events index page I have:
<h2>Upcoming Events</h2>
<br>
<%== pagy_bootstrap_nav(#pagy) %>
<br>
<div class="event-list-wrapper">
<% #events.upcoming_events.each do |event| %>
<%= render 'event', event: event %>
<% end %>
</div>
When I remove my upcoming_events scope, the records will display correctly.
In my event.rb model I have:
scope :upcoming_events, -> { where('event_start_date > ?', Time.now).or(where('event_end_date > ?', Date.yesterday)) }
Am I missing something in order to get pagy with work with my event scope?

Problems in Rails undefined method `map' for #<Contact:0x000000013aa76b48>

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

Get “wrong number of arguments” on ruby on rails

wrong number of arguments (given 2, expected 1)
SportsController
class SportsController < ApplicationController
def index
#sport = Sport.all
#events, #errors = Bapi::Inplay.all(query)
end
private
def query
params[:query, {}]
end
end
Sport index.html.erb
<% #sports.each do |sport| %>
<% #events(:sport_id => sport.id).each_slice(2) do |events| %>
I want send each sport.id to #enevts instance variable
Edited :
When send query as hash in SportsController its work!!
class SportsController < ApplicationController
def index
#sport = Sport.all
query = {:sport_id => 1}
#events, #errors = Bapi::Inplay.all(query)
end
private
def query
params[:query, {}]
end
end
Index.html.erb
<% #sports.each do |sport| %>
<% #events.each_slice(2) do |events| %>
params is a hash and method :[] can accept only 1 argument.
def query
params[:query] || {} # Will return :query part or empty Hash if it has nothing
end

Items controller index method executes twice losing local or instance variable settings

Update: I have posted this to github jquery-datatables-rails as it appears to be an issue with that gem or, more likely, my use of it. I am posting the updated copy here as well with more of a description to ask for help. Note that, while the respond_to block is executed twice, the datatable code is only executed on the second execution of the block.
I am trying to pass a variable named my_view to the Items Controller index method so that I can selectively display the results. The current code works, sort of... In the end, the view is not maintained and any action in the resultant table, such as scrolling, causes the table to revert to showing all items instead of the desired selection.
The basic problem is that the index method is always executed twice any time a button is clicked. The first time, the my_view variable is correctly set. The second time, it is always nil. The jquery-datatables-rails gem is executed on both passes and is probably involved. It almost seems like I get two different transactions. I've even tried instance variables and they are also nil during the second pass. I don't understand how or why this happens.
To "fix" this problem, I set session[:my_view] during the first pass and then do not set it again on the second pass. During the ItemsDatatable.new execution, I then must clear session[:my_view] or it would be retained for the next transaction giving incorrect results. However, this results in the problem that I stated in that any change to the view, such as scrolling, causes a reversion to showing all items instead of the desired selection.
Curiously, I don't seem to have any other controller methods with this sort of anomaly, or at least haven't noticed it. Can someone tell me why the index method is executed twice, and how I might resolve this issue? Thank you!
EDIT UPDATE: I have one other controller in the admin namespace that uses respond_to with HTML/JSON options. It also is executed twice, so it seems that may (?) be related. Still seems odd behavior to lose all variables and execute it the second time, but I don't know. Is it related and how might I resolve it? Thanks...
Here are my buttons:
<%= link_to 'My Items', items_path(my_view: current_associate.id), class: 'btn btn-primary kc-wide' %>
<%= link_to 'All Items', items_path(my_view: "all"), class: 'btn btn-primary kc-wide' %>
And the Items Controller with the index method:
class ItemsController < ApplicationController
def index
session[:my_view] ||= params[:my_view]
respond_to do |format|
format.html
format.json { render json: ItemsDatatable.new(view_context) }
end
end
end
Related routes, just in case?
POST /items_index(.:format) items#index
items GET /items(.:format) items#index
POST /items(.:format) items#create
new_item GET /items/new(.:format) items#new
edit_item GET /items/:id/edit(.:format) items#edit
item GET /items/:id(.:format) items#show
PATCH /items/:id(.:format) items#update
PUT /items/:id(.:format) items#update
DELETE /items/:id(.:format) items#destroy
The Rails datatable code is:
class ItemsDatatable < ApplicationController
before_action :check_if_associate
delegate :params, :h, :link_to, :edit_item_path, :new_item_path, :location, to: :#view
def check_params(params)
# When using the .json suffix in URI, need to stub params so that I can see that JSON information
params[:draw] = 1 if params[:draw].blank?
params[:columns] = Array.new(1, {data: 0, name: '', searchable: true, orderable: true, search: {value: '', regex: false}}) if params[:columns].blank?
params[:order] = Array.new(1, {column: 0, dir: 'asc'}) if params[:order].blank?
params[:start] = 0 if params[:start].blank?
params[:length] = 10 if params[:length].blank?
params[:search] = {value: '', regex: false} if params[:search].blank?
end
def initialize(view)
#view = view
check_params(params)
#view
end
def as_json(options = {})
{
draw: params[:draw].to_i,
recordsTotal: Item.count,
recordsFiltered: items.total_entries,
data: data
}
end
private
def data
todays_date = Time.zone.now.to_date
items.map do |item|
status = item.status
# If current associate has it, show where it is.
if item.checkedout?(#view.current_associate)
status = "#{item.status}-#{item.lastloc}"
end
# If it's checked out but someone else has it, show who has it.
if item.not_available? and !item.checkedout?(#view.current_associate)
status = "#{item.status}-#{item.location}"
end
# Override the above if in return status, just showing that.
status = item.status == "Rtn" ? "Rtn" : status
odometer = item.odometer.to_s.gsub(/(\d)(?=(\d{3})+(?!\d))/, "\\1,")
msrp = item.msrp.to_s.gsub(/(\d)(?=(\d{3})+(?!\d))/, "\\1,")
age_date = item.age_date.nil? ? todays_date : item.age_date.to_date
[
link_to(item.stock_number, edit_item_path(item)),
ERB::Util.h(item.year),
ERB::Util.h(item.make),
ERB::Util.h(item.model),
ERB::Util.h(item.color),
ERB::Util.h(status),
ERB::Util.h(odometer),
ERB::Util.h(msrp),
ERB::Util.h((todays_date - age_date).to_i)
]
end
end
def items
#items ||= fetch_items
end
def fetch_items
items = Item.order("#{sort_column} #{sort_direction}")
items = items.includes(:item_location, item_location: [:locator])
items = items.includes(:key, key: [:key_location])
items = items.page(page).per_page(per_page)
unless #view.session[:my_view].blank? || #view.session[:my_view] == "all"
associate = Associate.find(#view.session[:my_view]).name
associate = associate.gsub(/'/, "''") # .gsub(/'/, "\\\\\'")
items = items.where("clshadow = \'#{associate}\'")
end
#view.session[:my_view] = nil
if params[:search][:value].present?
items = items.where("stock_number ilike :search or yrshadow ilike :search or mkshadow ilike :search or mdshadow ilike :search or coshadow ilike :search or status ilike :search", search: "%#{params[:search][:value]}%")
end
items
end
def page
params[:start].to_i/per_page + 1
end
def per_page
params[:length].to_i > 0 ? params[:length].to_i : 10
end
def sort_column
columns = %w[stock_number yrshadow mkshadow mdshadow coshadow status odometer msrp age_date]
columns[params[:order][0][:column].to_i]
end
def sort_direction
params[:order][0][:dir] == "desc" ? "desc" : "asc"
end
end
Related JavaScript code:
var itemstable = $('#itemstable').DataTable({
responsive: true,
autoWidth: false,
pagingType: 'full',
jQueryUI: true,
processing: true,
serverSide: true,
ajax: {
url: 'items_index.json',
type: 'POST',
contentType: 'application/json',
dataType: 'json',
data: function(d) {
return JSON.stringify(d);
}
},
columns: [null, null, null, null, null, null,
{className: 'dt-right'},
{className: 'dt-right'},
{className: 'dt-right'}
]
});
And the view:
<div class="span9">
<p>
<table id="itemstable" class="display dt-responsive no-wrap table-striped" width="80%">
<thead>
<tr>
<th class="all">Stock No.</th>
<th class="all">Year</th>
<th class="all">Make</th>
<th class="min-tablet">Model</th>
<th class="min-tablet">Color</th>
<th class="all">Status</th>
<th class="desktop">Mileage</th>
<th class="desktop">MSRP</th>
<th class="desktop">Aged</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<%= link_to 'My Items', items_path(my_view: current_associate.id),
class: 'btn btn-primary kc-wide' %>
<%= link_to 'All Items', items_path(my_view: "all"),
class: 'btn btn-primary kc-wide' %>
<%= link_to 'Recent Items', x_logs_path,
class: 'btn btn-primary kc-wide' %>
<%= link_to 'Home', '/', class: 'btn btn-primary kc-wide' %>
</div>
Try this:-
def index
session[:my_view] = params[:my_view] unless request.xhr?
respond_to do |format|
format.html
format.json { render json: ItemsDatatable.new(view_context) }
end
end
It appears that the gem executes independently, without transferring control to the supplied code, during the first pass in order to set up the parameter list with all the desired variables. It then appears to force a reload to initiate the process with the parameter list as desired. I am assuming this from reviewing the variables during the first and second passes. During this process, it forgets any other variables, though I don't think that it should do that.
In any case, I have to use session variables to maintain status during this reload. I changed the controller index as follows, and then eliminated the clearing of session[:my_view] in my datatables controller.
def index
unless params[:my_view].blank?
session[:requested_view] = params[:my_view]
end
session[:my_view] = session[:requested_view]
respond_to do |format|
format.html
format.json { render json: CarsDatatable.new(view_context) }
end
end

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