update a cell of a table - ruby-on-rails

I have these lines in views/admins/index.html.erb
I tried to update my User table in the cell of the role_ids after pressing on update:
if worker.role_ids is [1], it will change to [2].
if worker.role_ids is [2], it will change to [1].
<td><%= worker.email %></td>
<td><%= worker.role_ids %></td>
<td><%= link_to 'edit', edit_admin_path(worker) %></td>
I can define edit and _form, but there is no elegant way?

You can do it via Ajax (I think that it is what you are looking for). You can call a remote action, passing the id of the object, and calling a method to update to the corresponding value. For example:
View
<%= link_to 'Change Role', change_admin_role_path(worker.id), :remote => true %>
Controller
def change_admin_role
#worker = User.find(params[:id])
#worker.change_role
end
Remember to add the route, also create the method change_role in the User model that will evaluate the actual value and make the change, and create a change_admin_role.js.coffee (or change_admin_role.js.erb) to make the changes over the view via Ajax.

Related

Ruby on Rails, reference custom parameter inside form to specific url

I need to do a specific form with a parameter that is not associated to the Model that im using. See, i have in my controller (and i can reference them in my view) a specific "Order" and an array of "Products".
#this controller responds to mydomain.com/new/order/:id_order
class MyController < ApplicationController
...
def my_page
#order = Order.find(params[:id_order])
#products = Product.all
end
...
end
In my view i need to render a list with all the products with their attributes (name, description, price), a small number field next to each product and a link to "Add" the product.
I can do the table to show every attribute in each individual product of my products array, problem is, i dont know how to create a number field next to each row in my table and a link to the "Add" action, which is just a point in my API, mydomain.com/add/product/:id_order/:id_product/:amount (alias as add_product_order)
:id_order correspond to the id of the order, which i have (#order.id)
:id_product correspond to the id of the specific product of the row, which i have (product.id)
:amount must be the amount specified by the user, but i have no idea how to reference it inside the view.
The rails helper form_for, form_tag etc ... requires the url to send the data however i cant use add_product_order_path because i would need the :amount parameter so it gives me an error (but if i use a constant amount like 1, it works).
In conclusion:
<% #products.each do |product| %>
<tr>
<td><%= product.name %></td>
<td><%= product.description %></td>
<td><%= product.price %></td>
<td><input type="number" name="amount" min="1"></td>
<td><%= link_to 'Add', add_product_order_path(id_order: #order.id, id_product: product.id, amount: *???* ), method: :post %></td>
</tr>
<% end %>
What would need to be in the ??? to send the value of the amount field to the add_product_order_path?
So, the amount value its an input with an unknown value. I highly recommend that use some JS to achieve this. Something like:
$('table td a').on('click', function(e) {
var amountVal = $(this).parent('tr').find('input').val();
var newUrl = location.href.replace("amount=", "amount="+amountVal);
$(this).attr('href', newUrl);
});
I hope it helps.
UPDATE
Sorry, did'nt saw that you're using method: :post, this generates a hidden form, you have to change the hidden input value. Its posible with javascript too:
$('table td a').on('click', function(e) {
var amountVal = $(this).parent('tr').find('input').val();
$(this).parent().find('input[name*="amount"]').val(amountVal);
});

Conflicting View Logic

I have a show page where I need to both show the student's units and create a unit for them. However an error is being incurred when trying to do both.
In my controller
def show
#student = Student.find(params[:id])
#unit = #student.units.build
#units = #student.units
end
In my view
<%= simple_form_for #unit, url: student_units_path(#student) %>
# form...
<% end %>
<% #units.each do |unit| %>
<tr>
<td><%= unit.course %></td>
<td><%= unit.mailing_date.strftime('%m/%d/%y') %></td>
</tr>
<% end %>
The unit.course call works and any call that is only the first child of unit, however when I call a second method on unit I get this error:
undefined method `strftime' for nil:NilClass
despite knowing that the unit exists, hence the first call working
It seems your issue is that unit.mailing_date is nil, for newly-built records.
One solution would be to define a default value for mailing_date, either at the database level or in your application. For example, you could do something like:
class Unit < ActiveRecord::Base
# ....
after_initialize :set_default_mailing_date
private
def set_default_mailing_date
self.mailing_date ||= Date.today
end
end
Or alternatively, you could leave the mailing_date as nil and handle this gracefully in the view:
<td><%= unit.mailing_date.try!(:strftime, '%m/%d/%y') %></td>
If you are using ruby version 2.3+, then I would advise using the built-in safe navigation operator, rather than ActiveSupport's try! method:
<td><%= unit.mailing_date&.strftime('%m/%d/%y') %></td>
Finally, if you went with the above choice to leave the mailing_date as nil, then perhaps you'd like to display some default value in its place - for example:
<td><%= unit.mailing_date&.strftime('%m/%d/%y') || 'Not set' %></td>
As an alternative, I assume you don't want the new unit bound to the form being rendered which is what is causing the error.
You could do
#units = #student.units.reject(&:new_record?)
To remove the newly built unit from the collection

Make method work with activerecord grouped objects

I have a bunch of objects, and I grouped them by the day they happened.
scope :grouped_by_user_with_total_time, lambda {
group(:user_id, :day).select('user_id, SUM(time_worked) AS time_total, day, editable, approvable, accepted, comments')
}
I also have some methods that change editable, approvable, and accepted. But now since they are grouped, I get this error when trying to approve grouped objects.
Couldn't find TimeLog without an ID
My approve method:
def approve
#time_logs = []
t = TimeLog.find(params[:time_logs])
if t.instance_of?(Array)
#time_logs = t
else
#time_logs << t
end
end
What do I have to change so that the methods can work on all of the hourlogs that are grouped together?
<% #time_logss.each do |timelog| %>
<% if timelog.user_id != current_user.id %>
<tr>
<!--<td><%# check_box_tag 'accept' %></td>-->
<td><%= timelog.id_name %></td>
<td><%= timelog.day.strftime("%B %d, %Y") %></td>
<td><%= timelog.time_total %></td>
<td><%= timelog.state %></td>
<% if timelog.state == "Submitted" %>
<td><%= link_to "Approve", approve_time_sheets_path(time_sheets: timelog), method: :put %></td>
You are trying to combine an aggregate function with the need to access unique data. When you use .select(''), you are telling AR which fields to populate into the object (even attributes that do not exist directly in the database).
If you add in time_logs.*, you'll lose the aggregate on time_worked, since you'll then be forced to add id to the group clause.
What you need to do have 1 instance var with the time_logs and one with the aggregate data:
#time_logs = TimeLog.all
#time_totals = TimeLog.grouped_by_user_with_total_time
Then, in the view, you can pluck out the correct total for each time_log. Although, I'm not clear on how you will be able to relate the specific time_log with it's aggregate equivalent.

Controller and view association and self.method still confuses me

Okay so in the index portion of my controller I set
#patients = Patient.all
then in patients_helper.rb
def race_abrev
return self.caucasian
end
where caucasian is an integer datatype column in the patients table
then in the view index.html.erb
<% #patients.each do |p| %>
<td><%= p.gender %></td>
<td><%= p.ethnicity %></td>
<td><%= p.race_abrev %></td>
<% end %>
I get a
undefined method `race_abrev' for #<Patient:0xb4d95cd8>
I've checked the table and I'm expecting patient.caucasian to return the integer 1, what am I missing..any insight to a fundamental misunderstanding I seem to have?
race_abrev is a helper, not a method on Patient:
<%= race_abrev(p) %>
And the helper itself would return p.caucasian, although it'd seem like you'd actually want to do something with the value of caucasian, like a compare or something.
All this said, I'm not sure why you're not defining it (or what "it" actually is) on the model, since so far it doesn't seem to have anything to do with the view, which is what view helpers are for.
If you're storing something in the DB you want to transform it may or may not belong in a view helper; if it's to turn it into something human-readable I'd be more likely to put it in the model.

Why does rails split my model named menuitem into menu_item when i run generate/scaffold? Is it breaking my app?

When I generated a scaffold for a model class named menuitem, it generates a class file for menuitem, but in the database creates menu_item and refers to the class in the views and controller as menu_item. This may be causing me quite a headache as im genereating a newsted show link, but its failing telling me missing method. The rake routes tells me the show route should be menu_menu_item, but when i do:
<td><%= link_to 'Show', menu_menu_item(#menu) %></td>
it doesnt work.
Is that because of the funky two word class name?
You must have generated either menu_item or menuItem or MenuItem. It doesn't know where one word stops and another starts unless you tell it.
Also, for your link_tos, you just need to append _path:
<td><%= link_to 'Show', menu_menu_item_path(#menu) %></td>
Well, actually, that looks a little wrong to me. That looks like you're trying to go to a single item, which I think will require you to specify both the menu and the item:
<td><%= link_to 'Show', menu_menu_item_path(#menu, #menu_item) %></td>
And to all the menu items in a menu:
<td><%= link_to 'Show', menu_menu_items_path(#menu) %></td>
The Pluralizer shows you show things should be named according to the Rails' conventions.

Resources