Rails and html form (materialize in this case) - ruby-on-rails

I am creating a table for my Product model. As headers, I will have the attribute names, and in the body the rows will represent a record for which I want to add values and then save .At the moment, I'm sketching this up as a HTML/CSS ( with Materialize)
<table>
<thead>
<tr>
<th>#</th>
<th>Date</th>
<th>Document</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>12/12/2017</td>
<div>
<td>
<select class = "browser-default">
<option value="" disabled selected>Choose your option</option>
<option value ="1">Option 1</option>
<option value ="2">Option 2</option>
</select>
</td>
<td class ="input-field col s6" >
<input id="last_name" type="text" class="validate">
</table>
If I want to keep the provided option, input, checkboxes from materialize, how can I save my record ( I want to still use input-field for e.g. and the value that I put there to be saved)
How can I adapt this to Rails form?

You'll want something like this in a html.erb file:
...
<tbody>
<% #products.each do |product| %>
<tr>
<td><%= product.id %></td>
<td><%= product.your_date_column %></td>
<%= form_for product do |f| %>
<td>
<%= f.select :browser_default, [["Option 1", 1], ["Option 2, 2"]], include_blank: "Choose your option" %>
</td>
<td class ="input-field col s6" >
<%= f.input :last_name %>
</td>
<% end %>
...
Couple of things to note:
You'll need to set #products in the relevant controller action.
This then iterates through these, creating a row for each product.
You'll need a submit button for this form, or to establish how to submit using AJAX. The former is simpler and would just need <%= f.submit %> adding to the row.
Hope that helps - let me know how you get on or if you have any questions :)

Related

how to save variable number of arguments of same type and same name in Rails?

A form is submitted in rails which have variable number of invoiced items, with a boolean value as true or false.How can I get all these values and save them in the database in the respective fields:
Request parameters are as:
<ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"cCQjRuaHnsIkCaffZfi6t3err4YPxrEWXSXNKy4gFmDUOtWt+T4JALddxkJWo/7giXD3dNXlvJz9tJ0EYDKKjQ==",
"invoiced_186"=>"1", "invoiced_187"=>"1", "invoiced_188"=>"1",
"invoiced_189"=>"1", "invoiced_190"=>"1",
"commit"=>"save", "controller"=>"cader/caders", "action"=>"add_invoiced_items", "id"=>"63813"} permitted: false>
Form templated is as:
<%= form_with url: cader_add_invoiced_items_path(#job_checkout.id), local: true do |f| %>
<table class="table table-bordered table-striped">
<thead>
<th>Item #</th>
<th>File</th>
<th>Service</th>
<th>Price $USD</th>
<th>Invoice</th>
</thead>
<tbody>
<% #done_job.each do |done_job| %>
<tr>
<td>
<%= f.check_box :"invoiced_#{done_job.id}" %>
<label>
<%= done_job.id %>
</label>
</td>
<td><%= done_job.file_name %></td>
<td><%= done_job.service %></td>
<td>$<%= done_job.amount %></td>
<td></td>
</tr>
<% end %>
</tbody>
</table>
<%= f.submit 'save' %>
How to manage them in server side because the field inoice_x is variable in number.
You can name your checkboxes like this
<checkbox name="invoiced[]" value="187">
You should receive an array of values checked. (Sorry, I can't test it ATM)
[187, 188]
Or do this
<checkbox name="invoiced[187]" >
Then, I believe you'd receive a hash
{187 = 1, 188 = 1}

Pass selected value to Rails controller

I've got a method named 'statement' in a balances controller (balances_controller.rb) that returns information from a specific date (#latestDate) to a view (statement.html.rb)
#latestDate = the most recent date in the 'date' column in the 'balances' table
In the view, I've also got a dropdown list of all the dates and when a date is selected, I'd like to be able to update the information so that in effect, the statement method is called again but the #latestDate is set to the selected value from the dropdown list.
How can I do this?
UPDATE:
I've modified my code with brito's suggestions. When I press the Search button, the form passes the following params:
?utf8=✓&date_id=30%2F12%2F2015&commit=Search
However, if I select a date and click Search, the #latestDate gets set and the h1 tag gets displayed correctly, but the rest of the data doesn't get returned.
CODE:
balances_controller.rb
....
def statement
#dates = Balance.select("distinct(date)").order('date desc')
#Updated
if (params[:date_id].blank?)
#latestDate = Balance.order('date desc').first.date
else
#latestDate = params[:date_id]
end
#summaryBalances = Balance.joins(:account).order('accounts.credit').where('date = :abc', {abc: #latestDate})
end
....
balances/statement.html.rb
....
<h1>Statement at <%= #latestDate %></h1>
#UPDATED
<%= form_tag("/statement", method: "get") do %>
<%= select_tag "date_id", options_for_select( #dates.collect {|d| [ d.date, d.date ] }) %>
<%= submit_tag("Search") %>
<% end %>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th>Account</th>
<th>Balance</th>
<th colspan="1"></th>
</tr>
</thead>
<tbody>
<% #summaryBalances.each do |balance| %>
<tr>
<td><%= balance.account.name %></td>
<td class='account-balance'><%= number_to_currency(balance.balance, unit: "£") %></td>
<td><%= link_to 'Edit', edit_balance_path(balance) %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
....
A "dropdown" is a kind of input (HTML <select>).
<input>s and <select>s must be within a <form> HTML element.
Using pure HTML
Whatever is in the <form> will be accessible in the params hash. So if you have a dropdown list, it should be within a <form> like this:
<form accept-charset="UTF-8" action="/yourroute" method="get">
<select name="car">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="opel">Opel</option>
<option value="audi">Audi</option>
</select>
</form>
In the example above, the selected value (e.g. "volvo") will be available in the controller within params["car"]. Note that you would still have to define /yourroute.
Using Rails' helper methods
Of course, Rails helps you generate forms and inputs. You can use Rails' form helpers for that. For example, the following generates a search form ("Search" label, text box for input and a button) that sends a GET to the /search route:
<%= form_tag("/search", method: "get") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %>
EDIT
To check and set #latestDate = balance[date_id] if the balance[date_id] was selected:
#latestDate ||= params[:balance[date_id]] unless params[:balance].blank?

how to pass all student_id in checkbox

I am having check box for selecting students in a particular class.But the unselected student id's are not passing via check box.Please help me. And also I have included coding below.
In View
<%= label_tag :students %>
<button type="button" id="check_all">
Check / Uncheck All
</button>
<table id = "mark">
<tr>
<td>
<table >
<thead>
<tr>
<td><strong>Students List</strong></td>
</tr>
</thead>
<tbody>
<% #student.each do |i| %>
<tr>
<td><%= check_box_tag :student, i.id %><%= i.first_name.capitalize %></td>
</tr>
<% end %>
</tbody>
</table>
<table>
<tr>
<td>
</tr>
</td>
</table>
</td>
</tr>
</table>
Js file
$('#check_all').on("click", function(){ $('input[type="checkbox"]').click(); });
You can achieve that in two ways at least.
one) deducting the submitted students from the students collection ids:
unselected_ids = #student.collect(&:id) - params[:student].collect(&:to_i)
two) setting another hidden field from client site using javascript
You can use hidden input with the same name before checkbox and zero value.
<input type='hidden' value='0' name='student'>
<input type='checkbox' value='1' name='student'>
When form submitted and checkbox is checked previous 0 value overwrites by 1. If checkbox not checked then 0 value sends to the controller.
Bur its works only if you have one value, but you have a lot of ids. And you must use student[] name in checkboxes, if you use student name then only last checked value sends in controller by in params[:student]
In this case use can use this construction in your code:
<% #student.each do |s| %>
<tr><td>
<%= hidden_field_tag "student_all[]", s.id %>
<%= check_box_tag "student[]", s.id %><%= s.first_name.capitalize %>
</td></tr>
<% end %>
And in controller get unchecked students like:
student_unchecked = params[:student_all] - params[:student]

Rails Update Single Attribute with Multiple Fields

I'm currently trying to make a form called countcash that allows users to input the actual number of quarters, dimes, nickels, pennies, twenties, tens, fives, ones and then the monetary value of any other items in the cash box and then when they hit submit, I want to total those values and set the cashstart field of my current shift record.
The real issue is that I'm not sure what my form is supposed to look like and how the controller/model are supposed to be setup in this instance.
I have a shift_id saved in a session[:shift_id] variable and the shift with that id is the shift that I want to modify with the calculated cashstart.
What does the <%= form_for %> tag need to look like if I want to follow the MVC correctly and how do I set up the controller/model to update the database with the calculated value? And what should I be setting the route to? I can't find anything like this on either stack overflow or other rails forums (Although you'd think that modifying a single attribute through multiple text fields would be pretty straight forward)
Just as a reference, this is the form I was using previously (To no avail)
app/views/countcash.html.erb
<%= form_for #shift do |f| %>
<table>
<tr>
<th>Coins</th>
<th></th>
</tr>
<tr>
<td>Quarters: </td>
<td><%= f.text_field :quarters %><br /></td>
</tr>
<tr>
<td>Dimes: </td>
<td><%= f.text_field :dimes %><br /></td>
</tr>
<tr>
<td>Nickels: </td>
<td><%= f.text_field :nickels %><br /></td>
</tr>
<tr>
<td>Pennies: </td>
<td><%= f.text_field :pennies %><br /></td>
</tr>
<tr>
<th>Bills</th>
<th></th>
</tr>
<tr>
<td>Twenties: </td>
<td><%= f.text_field :twenties %><br /></td>
</tr>
<tr>
<td>Tens: </td>
<td><%= f.text_field :tens %><br /></td>
</tr>
<tr>
<td>Fives: </td>
<td><%= f.text_field :fives %><br /></td>
</tr>
<tr>
<td>Ones: </td>
<td><%= f.text_field :ones %><br /></td>
</tr>
<tr>
<th>Other</th>
<th></th>
</tr>
<tr>
<td>Value (in $): </td>
<td><%= f.text_field :others %><br /></td>
</tr>
</table>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And here's my shifts_controller that doesn't do anything at the moment, since I'm not sure how I need to go about updating the attribute after the submit button is clicked
def countcash
#shift = Shift.find(session[:shift_id])
redirect_to(login_path)
end
I think you are almost there, presumably you have a named route which allows you to do this as your form declaration:
<%= form_for #shift, :url => countcash_shift_path(#shift) do |f| %>
If in doubt, run rake routes in your console to determine if such routes exist. If it doesn't, perhaps you would want to explore RESTful routes, which should look something like this in your routes.rb:
resources :shifts
Inside the countcash action in your controller, it's just a matter of doing this:
#shift = Shift.find(session[:id])
#shift.update_attributes(params[:shift]
This should work assuming that you have you have set up RESTful routes for your shift resource. Also, I am assuming that your model/database is set up with quarters, dimes, etc as individual fields (otherwise you will require some more advanced than update_attributes).
Since you are not having these individual fields in the database (as per your comment), you should not be putting as part of the model's form. So instead of:
<%= f.text_field :dimes %>
You'd do something like:
<%= text_field_tag :dimes, params[:dimes] %>
And inside your controller, you can just access them like so:
params[:dimes] + params[:quarters] # multiply as per currency logic
If you want to get a little more fancy, what you could do is write methods that take in these values, so you still leave the form as your current state, but add methods that take in the values and do something with it like so (for all types of currency, not just dimes):
def dimes=(value)
#running_total += value
end
In your controller, do this instead:
#shift.attributes = params[:shift]
So what happens is that when you pass your model the hash of attributes, it will try to assign the values based on the symbol names. So the value of dimes in params will be passed in as if this was being called:
#shift.dimes = params[:shift][:dimes]
I think that should work for you, assuming that you use #running_total for something. You could use #amount or something if that's what you already have as a model attribute.

Rails Has Many Forms

I'm having a bit of trouble getting forms for a has_many association to work for a shopping basket. The view is displaying the basket and has a table row for each item. Each row contains a text field so that the user can set the quantity.
The problem is that only the first item row quantity is being passed through in params, even if the second item's quantity has changed too.
Can anyone help please?
Thanks,
Roger
The output of params in the debugger is below, only one line_item is being passed through.
(rdb:2624) e params
{"commit"=>"Recalculate",
"authenticity_token"=>"7TKnhmbBPFiKLzVqTipzH8PDyCrOnKiFixGQ37XDGNY=",
"_method"=>"put", "utf8"=>"✓", "action"=>"update", "id"=>"4",
"line_item"=>{"quantity"=>"3", "id"=>"6"}, "controller"=>"baskets"}
app/controllers/basket_controller.rb
class BasketsController < ApplicationController
def update
begin
#basket = Basket.find(params[:id])
# Can't do anything here yet since the correct parameters aren't being passed through.
rescue ActiveRecord::RecordNotFound
logger.error "..."
end
redirect_to basket_path
end
end
app/views/baskets/show.html.erb
<%= form_for #basket do |f| %>
<table id="items">
<thead>
<tr>
<th>Name</th>
<th>Quantity</th>
<th>Price</th>
<th></th>
</tr>
</thead>
<tbody>
<% #basket.line_items.each do |item| %>
<%= form_for item do |g| %>
<tr class="<%= cycle('alternate', '') %>">
<td><%= item.product.name %></td>
<td>
<span class="decrement-quantity"><b>-</b></span>
<%= g.text_field :quantity %>
<span class="increment-quantity"><b>+</b></span>
</td>
<td class="price"><%= number_to_currency(item.total_price) %></td>
</tr>
<% end %>
<% end %>
<tr class="totals">
<td>Total</td>
<td><%= #basket.total_quantity %></td>
<td class="price"><%= number_to_currency(#basket.total_price) %></td>
<td></td>
</tr>
</tbody>
</table>
<%= f.submit 'Recalculate' %>
<% end %>
You're just creating a new form within the other form. Rails doesn't do anything magical just because you nest one form within another - which is what's causing the issue you're seeing.
The way to handle this situation is to use the fields_for helper and nested_attributes_for - see NestedAttributes for more information too.
I would checkout Railscasts: Complex Forms Part 1. After you watch that, you may be interested in watching Parts 2 & 3.
Ryan Bates covers using fields_for in an understandable and easy to learn fashion.

Resources