Dynamically update field value in Rails form - ruby-on-rails

I have a form in my ruby app which has a field total_hours_spent and different fields for breakup of the various activities like design_hours, analysis_hours, coding_hours etc.. I am looking for a mechanism where as soon as all the break up hours fields are filled, the total hours field should be updated dynamically. Sad thing is I dont know Ajax or Jquery. I know javascript but don't know how to use it with rails.
So what I am doing now is once the user submits the form, the values are calculated and then stored in the data base. Is there a way to dynamically display the field value using only rails?
Below is the form code: I would like to add two add a field total_hors which would be automatically populated with the value build_hours + test_hours + analysis_hours and other few fields..how to do this?
<%= nested_form_for(#rfsestimation) do |f| %>
<% if #rfsestimation.errors.any? %>
<h2> These errors prohibited the RFS from being saved </h2>
<font color="red">
<ul>
<% #rfsestimation.errors.full_messages.each do |msg| %>
<li><%= msg %> </li>
<% end %>
<% end %>
</ul>
</font>
<div class = "col-md-6">
<h4>IRIS AME RFS Estimation Summary Sheet</h4>
<table class = "table">
<tr> <td> RFS Number </td>
<td> <%= f.text_field :number, :placeholder => "Enter RFS Number" %> </td>
</tr>
<tr> <td> RFS Name </td>
<td> <%= f.text_field :name, :placeholder => "Enter RFS Name" %> </td>
</tr>
<tr> <td> Date of Estimation </td>
<td> <%= f.date_select :date_of_estimation, :placeholder => "Enter Date of Estimation" %> </td>
</tr>
<tr> <td> Request Type </td>
<td> <%= f.select :request_type_id , Rfsestimation.request_types.map { |k, v| [k.humanize, v] } %> </td>
</tr>
<tr> <td>Band</td>
<td> <%= f.select :band_id , Rfsestimation.band_types.map { |k, v| [k.humanize, v] } %> </td>
</tr>
</table>
<br/>
<table class = "table">
<thead>
<tr>
<td>Task</td>
<td>Effort(Hours)</td>
<td>Comments</td>
</tr>
</thead>
<tbody>
<tr>
<td>
Analysis / Requirements Gathering
</td>
<td>
<%= f.fields_for :rfstaskset do |rfs_task| %>
<%= rfs_task.number_field :analysis_hours %>
</td>
<td>
<%= rfs_task.text_area :analysis_comments, :size=> "40x1" %>
</td>
</tr>
<tr>
<td>
Design
</td>
<td>
<%= rfs_task.number_field :design_hours %>
</td>
<td>
<%= rfs_task.text_area :design_comments, :size=> "40x1" %>
</td>
</tr>
<tr>
<td>
Build
</td>
<td>
<%= rfs_task.number_field :build_hours %>
</td>
<td>
<%= rfs_task.text_area :build_comments, :size=> "40x1" %>
</td>
</tr>
<tr>
<td>
Test
</td>
<td>
<%= rfs_task.number_field :test_hours %>
</td>
<td>
<%= rfs_task.text_area :test_comments, :size=> "40x1" %>
</td>
</tr>
<tr>
<td>
UAT Support
</td>
<td>
<%= rfs_task.number_field :UATSupport_hours %>
</td>
<td>
<%= rfs_task.text_area :UATSupport_comments, :size=> "40x1" %>
</td>
</tr>
<tr>
<td>
Deployment Support and
Deployment instruction document
</td>
<td>
<%= rfs_task.number_field :DepSupport_hours %>
</td>
<td>
<%= rfs_task.text_area :DepSupport_comments, :size=> "40x1" %>
</td>
</tr>
<tr>
<td>
contingency
</td>
<td>
<%= rfs_task.text_field :hours_per_day, :value => "10%", :disabled => "true" %>
</td>
<td>
<%= rfs_task.text_area :contingency_comments, :size=> "40x1" %>
</td>
</tr>
</tbody>
<% end %>
</table>
<%= f.submit "Create RFS", class: "btn btn-success"%>
</div>
<div class = "col-md-6">
<table class="table">
<br/><br/>
<tr>
<td> Hours/day : </td> <td> <%= f.text_field :hours_per_day, :placeholder => "Enter hours per day", :value => "8.8", :disabled => "false" %> </td>
</tr>
<tr>
<td> Estimated Start Date : </td> <td> <%= f.date_select :estimated_start_date %> </td>
</tr>
<tr>
<td> Estimated End Date : </td> <td> <%= f.date_select :estimated_end_date %> </td>
</tr>
</table> <br/> <br/> <br/> <br/><br/> <br/><br/>
<%= f.fields_for :rfsnote do |rfs_note| %>
<%= rfs_note.text_area :notes, :size=> "60x20", :placeholder => "Enter RFS Notes" %>
<% end %>
</div>
<% end %>

You can use before_save callback
e.g
before_save :update_total_houres
def update_total_houres
total_hours_spent = design_hours + analysis_hours + coding_hour
end
also using JavaScript
$(document).ready(function(){
$('.hours').change(function() {
update_total_hours();
});
});
function update_total_hours()
{
var total = 0;
var analysis_hours = $(".analysis_hours").val();
var design_hours = $(".design_hours").val();
var coding_hour = $(".coding_hour").val();
total = sum all
//just update the total to sum
$('.total').text(total);
}

You can make callback before_create OR before_save in model, that will store automatically in database, like:
before_create :calculate_total_hours
def calculate_total_hours
total_hours_spent = design_hours, analysis_hours, coding_hours
end
You can also do via jquery, but do something in model will be strong business logic

so if you have the required values in the database,you can directly use it as instance variable and show it in your views..for example
def create
#here you create/save the required data in db
#user=User.new(params[:new])
if #user.save
#get the values you need
#time_used=#user.time_used
#build_hrs=#user.build_hrs
...
...
#and so on
#all these values will be available in the view directly
redirect_to users_show_url
else
render :new
end
end##method ends
end

Related

How can I access to nested fields attributes using nested_forms gem

I am using nested_forms gem in my project, nested_forms uses a partial view to render the line with my nested object attributes, here is my partial view code:
<tr class="fields">
<td>
<%= f.text_field :nombre, class: 'form-control craf' %>
</td>
<td>
<%
concat f.select :idtipodocumento, CrTipoDocumento.all.collect {|p| [ p.nombre, p.id ] }, {prompt: 'Seleccione el tipo de documento'}, :class=>'form-control'
%>
</td>
<td>
<%= f.text_field :documento, class: 'form-control', maxlength: '50' %>
</td>
<% if current_user.email.include? '#cifco.gob.sv' %>
<td>
<%= f.check_box :activo %>
</td>
<td>
<%= f.check_box :impresa %>
</td>
<td>
<%= f.check_box :extra %>
</td>
<% end %>
<td>
<%= f.link_to_remove raw('<i class="fa fa-minus-circle" aria-hidden="true"></i>'), :class =>'btn btn-danger hidden-print' %>
</td>
And here is the code block of the view where this partial is rendering:
<tbody>
<fieldset id="acreditados">
<%= f.fields_for :cr_acreditados, :wrapper => false %>
</fieldset>
</tbody>
So, what I want to do is evaluate if 'impresa' == false and only then render it, but if try f.impresa it says the method 'impresa' doesnt exist for f
Here is the form full code:
<%= nested_form_for(#cr_acreditacion_cliente, :validate => true) do |f| %>
<% if #cr_acreditacion_cliente.acreditaciones == nil %>
<% else %>
<table class="table table-striped table-bordered table-hover" id="AC">
<thead>
<tr>
<th>Evento</th>
<th>Cliente</th>
<th>Stand</th>
<th>Acreditaciones</th>
<th>Acreditaciones Disponibles</th>
<th>Tipo de Acreditacion</th>
</tr>
</thead>
<tbody>
<td><%= #cr_acreditacion_cliente.cr_evento.nombre %></td>
<td><%= #cr_acreditacion_cliente.cr_cliente.nombre %></td>
<td><%= #cr_acreditacion_cliente.cr_stand.codigo %></td>
<td><%= #cr_acreditacion_cliente.acreditaciones %></td>
<td>
<p hidden id="cnt"><%= #cr_acreditacion_cliente.acreditaciones %></p>
<p id="acd">
<%= #counter = #cr_acreditacion_cliente.acreditaciones - #cr_acreditacion_cliente.cr_acreditados.count %>
</p>
</td>
<td><%= #cr_acreditacion_cliente.cr_tipocre.tipo %></td>
</tbody>
</table>
<table class="table table-striped table-bordered table-hover" id="DAC">
<thead>
<tr>
<th>Nombre</th>
<th>Tipo de Documento</th>
<th>Documento</th>
<% if current_user.email.include? '#cifco.gob.sv' %>
<th>Activo</th>
<th>Impresa</th>
<th>Extra</th>
<% end %>
<th class="hidden-print">Acciones</th>
</tr>
</thead>
<tbody>
<fieldset id="acreditados">
<%= f.fields_for :cr_acreditados, :wrapper => false %>
</fieldset>
</tbody>
</table>
<div id="addBtn">
<% if #counter >= 1 %>
<p><%= f.link_to_add raw('<i class="fa fa-plus-circle" aria-hidden="true"></i>'), :cr_acreditados, id: 'btna', :class => 'btn btn-primary lta hidden-print', "data-target" => "#DAC" %></p>
<% else %>
<p class="text-center"><h3>No dispone de mas acreditaciones</h3></p>
<% end %>
</div>
<div class="actions text-center">
<%= f.submit "Guardar Credenciales", :class => 'btn btn-success hidden-print', data: { confirm: 'Favor verifique los datos antes de almacenarlos' }%>
</div>
<% end %>
<% end %>

Using each_slice to produce a table but with sub headings

I am using each_slice to output a two column table.
I would like to insert a title row when an attribute of the elements I am iterating changes.
I have :
all_users = Users.order('category, name asc').all
all_users.each_slice(2) do |two_users|
<tr>
<td style="text-align:right">
<%= two_users[0].category + ' - ' + two_users[0].name %>
</td>
<% if two_users[1].present? %>
<td>
<%= two_users[1].category + ' - ' + two_users[1].name %>
</td>
<td>
<% else %>
<td></td>
<% end %>
</tr>
<% end %>
And would like something like :
current_category = ''
all_users = Users.order('category, name asc').all
all_users.each_slice(2) do |two_users|
<% if two_users[0].category != current_category
current_category = two_users[0].category
%>
<tr><td colspan="2"><%= two_users[0].category %></td></tr>
<% end %>
<tr>
<td style="text-align:right">
<%= two_users[0].name %>
</td>
<% if two_users[1].present? %>
<td>
<%= two_users[1].name %>
</td>
<td>
<% else %>
<td></td>
<% end %>
</tr>
<% end %>
This doesn't work obviously in the case that two_users[1] has a new category.
I am trying to avoid the additional SQL queries of iterating through each category and requesting
the users for each independantly.
all_users.each_slice(2).with_object({cc: nil}) do |two_users, memo|
if category = two_users.detect { |u| u.category != memo[:cc] }
# print additional row or do whatever here
memo[:cc] = category
end
end
Enumerable#detect here returns either changed category or nil if there were no changes.
Sidenote: Try to DRY:
<td>
<%= two_users[1].name if two_users[1].present? %>
</td>

Format Active Record Data before rendering as JSON

I have a data table that i am going to convert to Ajax and have to format the JSON values into the right formats.
In this example how would i format the tables.created_at time-stamp to MM/DD
format...
tables = Table.where(:state => "Missouri")
respond_to do |format|
format.json { render json: tables }
end
In the DOM i would do a loop through the data and do this where i needed it: Chronic.parse(s.created_at.to_date).strftime("%m/%d")
And as you can see i have alot of additional formatting to do to the data before it is returned as JSON:
<% if #load_search.nil? %>
<tr></tr>
<% else %>
<% #load_search.each do |s| %>
<tr id="row_<%= s.id %>">
<td align="center">
<%= s.id %>
</td>
<td class="count" align="center">
<%= s.results %>
</td>
<td align="center">
<%= Chronic.parse(s.created_at.to_date).strftime("%m/%d") %>
</td>
<td align="center">
<% if s.equipment.empty? %>
All Equipment
<% else %>
<%= s.equipment.pluck(:code).to_s.gsub("[","").gsub(']','').gsub('"','') %>
<% end %>
</td>
<td align="center">
<% if s.origin_id.nil? %>
<%= s.origin_states %>
<% else %>
<%= Location.find(s.origin_id).cs unless s.origin_id.nil? %>
<% end %>
</td>
<td align="center">
<%= s.origin_radius_cs %>
</td>
<td align="center">
<% if s.dest_id.nil? %>
<%= s.dest_states %>
<% else %>
<%= Location.find(s.dest_id).cs unless s.dest_id.nil? %>
<% end %>
</td>
<td align="center">
<%= s.dest_radius_cs %>
</td>
<td align="center">
<%= s.length.to_s + ' ft.' unless s.length.nil? %>
</td>
<td align="center">
<%= s.weight.to_s + ',000 lbs' unless s.weight.nil? %>
</td>
<td align="center">
<% if s.ltl %>
Partial
<% elsif s.both %>
Full
<% else %>
Both
<% end %>
</td>
<td align="center">
<%= Chronic.parse(s.pickup.to_date).strftime("%m/%d") %>
</td>
<td align="center">
<%= Chronic.parse(s.delivery.to_date).strftime("%m/%d") unless s.delivery.nil?%>
</td>
</tr>
<% end %>
<% end %>
You can override the ActiveRecord getter as
class Model
def created_at
self[:created_at].strftime("%m/%d")
end
end

Render ajax query in Rails

I am tryign to render an Ajax query , but I just dont figure out how.
This is the form:
<%= form_tag(root_path, :method => "post",:id =>"formid", :remote => true) do %>
<%= label_tag(:number1, "El que quiero") %>
<%= text_field_tag :quiero, nil, :class => 'drug_autocomplete' %>
<%= hidden_field_tag :number1 %>
<%= label_tag(:number1, "El modelo que tengo") %>
<%= text_field_tag :tengo, nil, :class => 'drug_autocomplete' %>
<%= hidden_field_tag :number2 %>
<%= label_tag(:size1, "Talla de el que tengo") %>
<%= text_field_tag :size1%>
<%= submit_tag("Do it!",:id =>"submit_but") %>
<% end %>
This is pretty much the controller
def index
size1 = params[:size1]
number1 = params[:number1]
number2 = params[:number2]
quiero = params[:quiero]
tengo = params[:tengo]
if (item1 and item2)
#itemsok = Contribution.where("first_item_id = ?",item1.id).where("second_item_id = ?",item2.id).where("second_item_grade = ?",size1)
end
Ok, so when I push the button to send, I can see that the consult in the database is being made, when I write correct values it returns it and all works perfectly.
What I dont know how to do is to render the items from the query.
In the view I have a table where I want to fill the information in...
I've already done it without AJAX, and it is like this.
<%if not #itemsok.nil?
#itemsok.each do |searches|
%>
<table>
<tr>
<td style="width:100px;"><%= searches.first_item.description %> </td>
<td style="width:150px; font-size:30px;"><%= searches.first_item_grade %> </td>
<td style="width:150px;"><%= searches.second_item.description %> </td>
<td style="width:150px; font-size:30px;"><%= searches.second_item_grade %> </td>
<td style="width:150px; font-size:18px;">Show </td>
</tr>
</table>
Ok, so it takes the variable in the controller, and if is not nill, it renders the data (wich in a normal request, I can access reloading the page)
How can I render the items from my query?
Any hint would be very appreciated.
Thank you.
For example, _search.html.erb
<%if not #itemsok.nil?
#itemsok.each do |searches|
%>
<table>
<tr>
<td style="width:100px;"><%= searches.first_item.description %> </td>
<td style="width:150px; font-size:30px;"><%= searches.first_item_grade %> </td>
<td style="width:150px;"><%= searches.second_item.description %> </td>
<td style="width:150px; font-size:30px;"><%= searches.second_item_grade %> </td>
<td style="width:150px; font-size:18px;">Show </td>
</tr>
</table>
search.js.erb
$('#container').html("<%= escape_javascript(render :partial => 'search/search')%>");

How to manage multiple non nested Models in a rails form

i have two tables(adverb,word) and two controllers(adverbs,words).i want to have one form to add and edit the records of two tables.
adverb controller:
class AdverbsController < ApplicationController
def new
#adverb=Adverb.new
end
def create
#adverb=Adverb.create(params[:adverb])
if #adverb.save
redirect_to :action => 'index'
else
render :action => 'new'
end
end
def index
#adverb =Adverb.find(:all)
end
def edit
#adverb =Adverb.find(params[:id])
end
def update
if #adverb.update_attributes(params[:adverb])
redirect_to :action => 'index'
else
redirect_to :action => 'edit'
end
end
end
and words controller:
class WordsController < ApplicationController
def new
#word=Word.new
end
def create
#word=Word.create(params[:word])
if #word.save
redirect_to :action => 'index'
else
render :action => 'new'
end
end
def index
#word=Word.find(:all)
end
def edit
#word=Word.find(params[:id])
end
def update
if #word.update_attributes(params[:word])
redirect_to :action => 'index'
else
redirect_to :action => 'edit'
end
end
end
I use Partial form
<html>
<div id="tabs">
<ul>
<li>word </li>
<li>Adverb </li>
</ul>
<div id="tabs-1">
<table >
<tr>
<td align="right">
Artikel :
</td>
<td align="center">
<%= w.label :Artikel ,'der' %><%= w.radio_button :Artikel,'der',:checked =>false%>
<%= w.label :Artikel ,'die' %><%= w.radio_button :Artikel,'die',:checked =>true %>
<%= w.label :Artikel ,'das' %><%= w.radio_button :Artikel,'das',:checked =>false %>
</td>
</tr>
<tr>
<td align="right">
Neues Wort:
</td>
<td>
<%= w.text_field :Name ,:size => '31*45'%>
</td>
</tr>
<tr>
<td align="right">
Synonome :
</td>
<td>
<%= w.text_field :syn ,:size => '31*45'%>
</td>
</tr>
<tr>
<td align="right">
Bedeutung :
</td>
<td>
<%= w.text_area :bedeutung , :size =>'30*45' %>
</td>
</tr>
<tr>
<td align="right">
Beispiel :
</td>
<td>
<%= w.text_field :beispiel ,:size => '31*45' %>
</td>
</tr>
<tr>
<td>
Kommentar:
</td>
<td>
<%= w.text_area :kommentar ,:size =>'30*45' %>
</td>
</tr>
<tr>
<td align="center">
<%= w.submit submit_lable %>
</td>
</tr>
</table>
</div>
<div id="tabs-2">
<%= fields_for (#adverb) do |av| %>
<table>
<tr>
<td align="right">
Adverb :
</td>
<td>
<%= av.text_field :name %>
</td>
</tr>
<tr>
<td align="right">
Bedeutung :
</td>
<td>
<%= av.text_field :bedeutung %>
</td>
</tr>
<tr>
<td align="right">
Synonome :
</td>
<td>
<%= av.text_field :syn %>
</td>
</tr>
<tr>
<td>
<%= w.submit submit_lable %>
</td>
</tr>
</table>
<% end %>
</div>
</div>
</html>
and im my new.html.erb :
<html>
<body>
<%= form_for(#word) do |w| %>
<%= render :partial => 'form',:locals => {:w =>w,:submit_lable =>'mmmm'} %>
<% end %>
</body>
</html>
but an error occured:
NoMethodError in Words#new
Showing /home/babak/kurs/app/views/words/_form.erb where line #197 raised:
undefined method `model_name' for NilClass:Class
how can i solve my problem?
thank you for your helps
I assume this exception is raised when getting the new action of the words controller. In your _form.html.erb, you have the following code:
<%= fields_for (#adverb) do |av| %>
<table>
<tr>
<td align="right">
Adverb :
</td>
<td>
<%= av.text_field :name %>
</td>
</tr>
<tr>
<td align="right">
Bedeutung :
</td>
<td>
<%= av.text_field :bedeutung %>
</td>
...
</table>
<%= end %>
I see nowhere in your new action of the words controller where #adverb is declared. Instance variables default to nil, which is why you see this error.

Resources