This app consists of a form to submit and currently I am trying to print a few rows of a table. This is working, but unfortunately I am also getting a single long string of the entire database table attributes. There is nothing in the code that I have written (I believe) which would cause this. I fear that this is some unseen rails magic, any insight would be great!
The controller:
class StudentsController < ApplicationController
def new
#student = Student.new
end
def create
student_map = {"student_id" => params[:student_id], "student_name" => params[:student_name],
"major" => params[:major], "minor" => params[:minor], "other_information" => params[:other_information],
"class_year_id" => params[:class_year_id], "hours_st" => params[:hours], "qr_id" => qr_id,}
if (newStudentRow.save)
redirect_to action: 'index'
else
render action: 'new'
end
end
def index
#students = Student.all
end
end
The Index view:
<h1>Students#index</h1>
<p>Find me in app/views/students/index.html.erb</p>
<table>
<thead>
<tr>
<th>Student Name</th>
<th>ID</th>
</tr>
</thead>
<tbody>
<%= #students.each do |s| %>
<tr>
<td><%= s.student_name %></td>
<td><%= s.student_id %></td>
</tr>
</tbody>
<% end %>
</table>
After entering data and submitting the form, this link shows the following output:
Thanks for the help!
Change:
<%= #students.each do |s| %>
To this:
<% #students.each do |s| %>
In Ruby, each executes the block for each element AND returns the array. Having the = outputs the array, which is why you are seeing that long string.
Related
I have an XML object that's loaded into a Ruby hash. The goal is to display some complex XML from a web service in a webpage.
The tricky thing is the XML can look different depending on what XML data is returned from the web service.
I have ERB code that looks like this...
...
<p>Name:</p><%= #some_hash['root']['data']['name'] %>
<table>
<tr><td><span class="label">Total:</span><%= #some_hash['root']['data']['subdata'] %></td></tr>
<tr><td><span class="label">Rate:</span><%= #some_hash['root']['data']['subdata1'] %></td></tr>
</table>
<table>
<tr>
<th>Column A</th>
<th>Column B</th>
</tr>
<% #some_hash['root']['data']['subdata2'].each do |value| %>
<tr>
<td><%= #value['A'] %></td>
<td><%= #value['B'] %></td>
</tr>
<% end %>
</table>
...
I put the "#" in front of the variables to check for nil. That didn't do much. I'm not sure if this is the best approach. How do I cleanly iterate through the ERB and only execute if the value exists?
Hash#dig and the safe navigation operator will do this:
<% if subdata = #some_hash&.dig('root', 'data', 'subdata') %>
<tr><td><span class="label">Total:</span><%= subdata %></td></tr>
<% end %>
dig will attempt to extract the nested value, returning nil if any part of it is unavailable. The safe navigation operator &. prevents the NoMethodError when calling .dig if #some_hash is nil.
Use a helper
def data_table(source)
if subdata = source&.dig('root', 'data', 'subdata')
h.content_tag :table do
h.content_tag :tr do
h.content_tag :td do
h.content_tag :span, 'Total:'
subdata
end
end
end
end
end
erb
<p>Name:</p><%= #some_hash['root']['data']['name'] %>
<%= data_table(#some_hash) %>
<% if subdata = (#some_has || {}).dig('root', 'data', 'subdata') %>
<tr><td><span class="label">Total:</span><%= subdata %></td></tr>
<% end %>
What I am trying to accomplish is a simple "toggle" checkbox for On/Off for a view which contains records from a model.
I have attempted to look into a "hidden" value, but it doesn't appear to work as intended.
How to get blank checkboxes to pass as false to params
When I've added: <%= hidden_field_tag "category_ids[]", '' %>
I receive Couldn't find Category with 'category_name'= when unchecking.
Essentially, the table is a Model.all, but I want to be able to modify the key value on an is_active column to true or false, depending on if the box is checked, or not. Currently, I can accomplish this for "checking" the box. But, not unchecking (passes null). I am trying accomplish this is one swoop rather than making all my checkes, and another pass for my unchecked. And, also bypassing the show/edit process. The table size is rather small, so I am not concerned with latency.
I have attempted to search as much as I could, but am at a loss. With what I've found I can do one or the other, but not both unfortunately, and I would greatly appreciate any guidance.
My view:
<h4>Categories</h4>
<%= form_tag enable_categories_path, method: :put do |f| %>
<table id="myTable" class="table table-bordered table-striped">
<tr>
<th>Enable</th>
<th>Category Name</th>
<th>Active</th>
</tr>
<tbody>
<% #categories.each do |category| %>
<tr>
<td>
<%= check_box_tag "category_ids[]", category.id, category.is_active == 1 ? 'checked' : nil %>
</td>
<td><%= link_to category.category_name, category %></td>
<td><%= category.is_active == 1 ? 'Yes' : 'No' %></td>
</tr>
<% end %>
</tbody>
</table>
<%= render 'settings/button' %>
<% end %>
Here, the checkboxes are grabbing their state from the model itself for the corresponding record, so if no action is taken on the checkbox it remains the same (or passes state back)
My controller:
class CategoriesController < ApplicationController
before_action :set_category, only: [:show, :edit, :update]
def index
#categories = Category.all.order(:category_sort)
end
def show
#category = Category.find(params[:id])
end
def edit
end
def update
if #category.update(category_params)
redirect_to categories_path
else
render :edit
end
end
def enable
Category.update(params[:category_ids], params[:category_ids].map{ |e| {is_active: true} })
redirect_to categories_path
end
private
def set_category
#category = Category.find(params[:id])
end
def category_params
params[:category].permit(:id, :category_name, :is_active)
end
end
Currently, I'm only passing is_active: true, until I can figure a way to pass ALL checkbox states.
My model:
class Category < ActiveRecord::Base
self.table_name = 'categories'
has_many :metrics
end
My route:
resources :categories do
collection do
put :toggle
end
end
Everything appears to pass correctly for checked boxes. But, nothing appears in the logs for when something is unchecked.
When I've run into situations like this in Rails I usually end up using AJAX rather than mass assignment. It's actually rather easy. At least easier for me than learning the inner workings of the check_boxes and collection_check_boxes, LOL
A simple Categories table:
<table>
<thead>
<tr>
<th>Category</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<% #categories.each do |category| %>
<tr>
<td><%= category.category_name %></td>
<% status = category.is_active? ? 'Active' : 'Inactive' %>
<td id="<%= category.id %>" ><button class="button_<%= status %>"><%= link_to status, toggle_active_path(:id => category.id), :method => :post, :remote => true %></button></td>
</tr>
<% end %>
</tbody>
</table>
The lines to note are the embedded ruby setting the status variable. This is used to set the value of the class for the button. In the CSS file the button class button_Active sets the color to green and button_Inactive makes it red. It also uses this variable to set the text of the button.
Create a method in the controller that toggles the status:
def toggle_is_active
#category.toggle!(:is_active) #flips the boolean on is_active
respond_to do |format|
format.html { redirect_to(#category) }
format.js
end
Be aware that .toggle! will bypass model validations and save. If you need to ensure validations run you can use #category.toggle(:is_active).save
This will respond to format.js and call a very small file called toggle_is_active.js.erb:
$('#<%= #category.id %>').html('<%= escape_javascript(render :partial => 'toggle_active') %>');
This targets the id of the html element that we set to the id of the category in the table row.
This calls a partial called _toggle_active.html.erb and updates the appropriate <td> with the new html:
<% status = #category.is_active? ? 'Active' : 'Inactive' %>
<button class="button_<%= status %>"><%= link_to status, toggle_active_path(:id => #category.id), :method => :post, :remote => true %></button>
Now all you need is a route to access the AJAX link:
routes.rb:
post 'toggle_active' => 'categories#toggle_is_active'
Here is a working example you can clone on github. It has the stylesheets to get the look above. I think you can extrapolate this for almost any situation:
https://github.com/Beartech/category_boxes
Let's consider what's going on here:
def enable
Category.update(params[:category_ids], params[:category_ids].map{ |e| {is_active: true} })
redirect_to categories_path
end
Can you post what params[:category_ids] looks like here? the map here doesn't quite make sense. Also, what is the data type of is_active in the database?
I'm new at Ruby on Rails (I started studying this week by myself) and I'm facing some issues that I cannot solve.
I have created a project called 'projeto_ajuda' and i'm using mysql database. I access the aplication on http://localhost:3000/menu/index. It shows me a table with 5 columns, and the last one, is for a button.
What I want is: when the button is clicked, it calls a method from the controller that 'refresh' the table with a new select (i add a new condition in where statement).
Ps¹: the view show to filled rows in the table, but when I click on the button, nothing changes on the view, but the URL does: http://localhost:3000/menu/index.%23%3CMenu::ActiveRecord_Relation:0x007f5ce5891608%3E?id=6
Ps²: If I refresh_table(6) instead of refresh_table(nil) on the index method, it works just fine, selecting what I want from the database.
And if I look at the database, there is a record with the id 6.
menu_controller.rb:
class MenuController < ApplicationController
helper :all
def index
refresh_table(nil)
end
def abrir
refresh_table(params[:id])
end
private
def refresh_table(id)
if(id.nil?)
#menus = Menu.where("codigopai IS NULL")
else
#teste = Menu.find(id)
#menus = Menu.where("codigopai = '" + #teste.codigopai.to_s + #teste.codigo.to_s + "'")
end
end
end
index.html.erb:
<h1> List all </h1>
<table>
<tr>
<th>Codigo</th>
<th>CodigoPai</th>
<th>Descrição</th>
<th>Conteúdo</th>
<th></th>
</tr>
<% #menus.each do |m| %>
<tr>
<td><%= m.codigo %></td>
<td><%= m.codigopai %></td>
<td><%= m.descricao %></td>
<td><%= m.conteudo %></td>
<td><%= button_to 'Abrir', menu_index_path(#menus, :id => m.id), method: :post %></td>
</tr>
<% end %>
</table>
routes.rb:
Rails.application.routes.draw do
resources :menus
post 'menu/index'
get 'menu/index'
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
Try this
menu_controller.rb
class MenuController < ApplicationController
helper :all
def index
refresh_table(params[:id])
end
private
def refresh_table(id)
if id
#teste = Menu.find(id)
#menus = Menu.where(codigopai: "#{#teste.codigopai}#{#teste.codigo}")
else
#menus = Menu.where(codigopai: nil)
end
end
end
index.html.erb
<h1> List all </h1>
<table>
<tr>
<th>Codigo</th>
<th>CodigoPai</th>
<th>Descrição</th>
<th>Conteúdo</th>
<th></th>
</tr>
<% #menus.each do |m| %>
<tr>
<td><%= m.codigo %></td>
<td><%= m.codigopai %></td>
<td><%= m.descricao %></td>
<td><%= m.conteudo %></td>
<td><%= button_to 'Abrir', menu_index_path(id: m.id), method: :post %></td>
</tr>
<% end %>
</table>
I think you can read Query with Active Record and routing
currently im accessing my join table directly. the reason im doing this is because i only want the staff to be able to adjust the status
im facing problem with
undefined method order_task_path' for #<#<Class:0x00000009bf62c0>:0x0000000a6d7c70>`
with parameter Parameters:
{"id"=>"1,1"}
i'm able to display the join table according to my need. the problem is when i try to display it in edit.
here is my ordertask controller
class OrdersTasksController < ApplicationController
before_action :set_status, only: [:show]
def index
#orders = Order.all
##status = OrderTask.includes(:task,:order).where(order_id: params[:id])
end
def edit
#status = OrderTask.find(params[:id])
end
def show
end
def update
respond_to do |format|
if #status.update(order_params)
format.html { redirect_to #status, notice: 'Order was successfully updated.' }
format.json { render :show, status: :ok, location: #order }
else
format.html { render :edit }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_status
#status = OrderTask.includes(:task).where(order_id: params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_params
params.require(:order_task,:order).permit(:id,:order_id,:status)
end
end
my show.html.erb
<p id="notice"><%= notice %></p>
<table class="table table-hover">
<tr>
<td><h4>Order Number : <%= #status.first.order.order_number %></h4>
</td>
</tr>
<tr>
<td>Task
</td>
<td>Status:
</td>
</tr>
<tr>
<% #status.each do |i| %>
<td><%= i.task.task_name %>
</td>
<td><%= i.status %>
</td>
<td><%= link_to 'Edit', edit_orders_task_path(i) %></td>
</tr>
<% end %>
</table>
<%= link_to 'Back', orders_tasks_path %>
my _form.html.erb
<%= form_for(#status) do |f| %>
<% if #status.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#status.errors.count, "error") %> prohibited this order from being saved:</h2>
<ul>
<% #status.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<table class="table table-hover">
<tr>
<td><%= f.label "List of task" %>
</td>
<td><%= f.label "Status" %>
</td>
</tr>
<tr>
<td><%= f.task_id %>
</td>
<td><div class="dropdown">
<%= f.select(:status,['In progress', 'Completed'], {}, {class: "control"})%> </div>
</td>
</tr>
<tr>
<td>
</td>
<td><%= f.submit %>
</td>
</tr>
</table>
<% end %>
and my routes
resources :orders
resources :services
resources :tasks
resources :customers
resources :staffs
resources :orders_tasks
root 'staffs#index'
and lastly my ordertask model
class OrderTask < ActiveRecord::Base
self.primary_key = [:order_id,:task_id]
self.table_name = "Orders_tasks"
belongs_to :order
belongs_to :task
end
hope u guys can give suggestion or something to help me with this. thx in advance.
EDIT
here is my route.rb
C:\Users\Idea\DHMS>rake routes
Prefix Verb URI Pattern Controller#Action
orders GET /orders(.:format) orders#index
POST /orders(.:format) orders#create
new_order GET /orders/new(.:format) orders#new
edit_order GET /orders/:id/edit(.:format) orders#edit
order GET /orders/:id(.:format) orders#show
PATCH /orders/:id(.:format) orders#update
PUT /orders/:id(.:format) orders#update
DELETE /orders/:id(.:format) orders#destroy
services GET /services(.:format) services#index
POST /services(.:format) services#create
new_service GET /services/new(.:format) services#new
edit_service GET /services/:id/edit(.:format) services#edit
service GET /services/:id(.:format) services#show
PATCH /services/:id(.:format) services#update
PUT /services/:id(.:format) services#update
DELETE /services/:id(.:format) services#destroy
tasks GET /tasks(.:format) tasks#index
POST /tasks(.:format) tasks#create
new_task GET /tasks/new(.:format) tasks#new
edit_task GET /tasks/:id/edit(.:format) tasks#edit
task GET /tasks/:id(.:format) tasks#show
PATCH /tasks/:id(.:format) tasks#update
PUT /tasks/:id(.:format) tasks#update
DELETE /tasks/:id(.:format) tasks#destroy
customers GET /customers(.:format) customers#index
POST /customers(.:format) customers#create
new_customer GET /customers/new(.:format) customers#new
edit_customer GET /customers/:id/edit(.:format) customers#edit
customer GET /customers/:id(.:format) customers#show
PATCH /customers/:id(.:format) customers#update
PUT /customers/:id(.:format) customers#update
DELETE /customers/:id(.:format) customers#destroy
staffs GET /staffs(.:format) staffs#index
POST /staffs(.:format) staffs#create
new_staff GET /staffs/new(.:format) staffs#new
edit_staff GET /staffs/:id/edit(.:format) staffs#edit
staff GET /staffs/:id(.:format) staffs#show
PATCH /staffs/:id(.:format) staffs#update
PUT /staffs/:id(.:format) staffs#update
DELETE /staffs/:id(.:format) staffs#destroy
orders_tasks GET /orders_tasks(.:format) orders_tasks#index
POST /orders_tasks(.:format) orders_tasks#create
new_orders_task GET /orders_tasks/new(.:format) orders_tasks#new
edit_orders_task GET /orders_tasks/:id/edit(.:format) orders_tasks#edit
orders_task GET /orders_tasks/:id(.:format) orders_tasks#show
PATCH /orders_tasks/:id(.:format) orders_tasks#update
PUT /orders_tasks/:id(.:format) orders_tasks#update
DELETE /orders_tasks/:id(.:format) orders_tasks#destroy
root GET / staffs#index
According to the error message undefined method order_task_path' for #<#<Class:0x00000009bf62c0>:0x0000000a6d7c70>, the url helper method does not exist.
you can rake rake routes in the terminal to get all the routes and route helpers.
resources :orders do
resources :tasks
end
generate the following routes and helpers.
order_tasks GET /orders/:order_id/tasks(.:format) tasks#index
POST /orders/:order_id/tasks(.:format) tasks#create
new_order_task GET /orders/:order_id/tasks/new(.:format) tasks#new
edit_order_task GET /orders/:order_id/tasks/:id/edit(.:format) tasks#edit
order_task GET /orders/:order_id/tasks/:id(.:format) tasks#show
PATCH /orders/:order_id/tasks/:id(.:format) tasks#update
PUT /orders/:order_id/tasks/:id(.:format) tasks#update
DELETE /orders/:order_id/tasks/:id(.:format) tasks#destroy
resources :orders do
resources :orders_tasks
end
generate the following routes and helpers.
order_orders_tasks GET /orders/:order_id/orders_tasks(.:format) orders_tasks#index
POST /orders/:order_id/orders_tasks(.:format) orders_tasks#create
new_order_orders_task GET /orders/:order_id/orders_tasks/new(.:format) orders_tasks#new
edit_order_orders_task GET /orders/:order_id/orders_tasks/:id/edit(.:format) orders_tasks#edit
order_orders_task GET /orders/:order_id/orders_tasks/:id(.:format) orders_tasks#show
PATCH /orders/:order_id/orders_tasks/:id(.:format) orders_tasks#update
PUT /orders/:order_id/orders_tasks/:id(.:format) orders_tasks#update
DELETE /orders/:order_id/orders_tasks/:id(.:format) orders_tasks#destroy
http://guides.rubyonrails.org/routing.html#nested-resources
this is my controller :-
class MessagesController < ApplicationController
def new
#messages = Message.all
end
def show
#messages = Message.all
end
end
This is new.html.erb :-
<%= #messages.name %>, <%= #messages.email %>
this is my show.html.erb :-
<h1>Inbox</h1>
<table width="500" height="20" border="0" class="borderTable inlineTable" >
<tr>
<th>FROM</th>
<th>SUBJECT</th>
<th>RECEIVED AT</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #messages.each do |m| %>
<% if m.to == get_user %>
<% if m.have_read == 0 %>
<font color="red">
<tr>
<td><font color="blue"><%= link_to m.from, "#" %></font></td>
<td><font color="blue"><%= link_to m.subject, "#" %></font></td>
<td><font color="blue"><%= link_to m.created_at, "#" %></font></td>
</tr>
<% else %>
<tr>
<td><%=link_to m.from , "#"%></td>
<td><%=link_to m.subject , "#"%></td>
<td><%=link_to m.created_at, "#" %></td>
</tr>
<% end %>
<% end %>
<% end %>
</table>
<br>
I when i try to access the new page by typing in "http://localhost:3000/messages/new" I get the correct page .
But when i try to access "http://localhost:3000/messages/show" I receive an error.
I have made the show.html.erb manually . Am i supposed to specify something in the routes.rb file , for it to work correctly?
this is my routes.rf file :-
Rails.application.routes.draw do
get 'messages/new'
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
get 'newmain' => 'users#newmain'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :users
end
Yes, you're supposed to either set messages as a resource or specify the route:
Specifying route:
get 'messages/show' => 'messages#show'
Creating resource:
resources :messages
I suggest the first one, and I suggest you either always write the => (I do) or never do, as it can become pretty confusing, pretty quickly.