rails not updating session hash on ajax request without pry - ruby-on-rails

I'm trying to develop a cart system(for a practice e-commerce project) on rails 6.
The code(explaination):
I have a link with class attribute "add_to_cart_link" then I use a jquery to select the elements with the mentioned class and set a on click listener on them. The click listener send an ajax request to 'shopping_experience/add_to_cart'.The control then moves to "add_to_cart" method inside shoppingExperience controller.
the problem is that even though the add_to_cart method is executed, it doesn't update my session hash unless i use "binding.pry"(this is a feature of pry gem which is used for debugging). during pry whenever check the state of the hash(session hash) it's always what its suppose to be and changed when i add some thing to cart.
here is my view template(index.html.erb):
<p id="notice"><%= notice %></p>
<%= link_to 'view cart', display_cart_path %>
<h1>Items</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Price</th>
<th>Quantity</th>
<th>Category</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #items.each do |item| %>
<tr>
<td><%= item.name %></td>
<td><%= item.price %></td>
<td><%= item.quantity %></td>
<td><%= item.category.title %></td>
<td><%= link_to 'Show', item %></td>
<td> <a class="add_to_cart_link" data-item_id=<%=item.id %> href="#"> add to cart button</a>
</td>
<td><%= link_to 'Edit', edit_item_path(item) %></td>
<td><%= link_to 'Destroy', item, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
here is my custom (myjs.js.erb)
$( document ).ready(function() {
$(document).on('click', 'a.add_to_cart_link', function() {
console.log(this);
console.log($('meta[name="csrf-token"]').attr('content'));
var id = $(this).attr("data-item_id")
console.log(id)
$.ajax({
method: "POST",
headers: {'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')},
url: 'shopping_experience/add_to_cart',
data: { item_id: id },
})
});
});
add_to cart method:
def add_to_cart
if !session[:current_cart]
session[:current_cart] = {:shex_id => session[:current_cart_id] }
end
#checks if session hash's current cart key doesn't have params[:item_id] key, value pair
if !session[:current_cart].key?(params[:item_id])
# set {units: 1} as params[item_id] key's value
session[:current_cart][params[:item_id]] = {}
session[:current_cart][params[:item_id]][:quantity] = 1
else
#else increment value of quantity
session[:current_cart][params[:item_id]]["quantity"] = session[:current_cart][params[:item_id]]["quantity"] + 1
#ShexItem.create(item_id: params[:item_id], shopping_experience_id: session[:current_cart_id] )
end
binding.pry
puts(' at to cart method end')
end
so if remove the the bindin.pry from the end my session has isn't changed at all and i do get a "at the end of add to cart method" message in my terminal(even when i remove the binding.pry). this means that the add to card method is indeed called but my session doesn't get updated and if use pry to debug whats wrong it starts to work. I feel it might be related using an ajax request because maybe the session doesnt get updated or refreshed . i really am struggling with this can anyone help?
here is the github repo: https://github.com/HaroonAzhar/ship-shop (i think the repo is public),
if anyone wants to look up the code more.

So I got it to work. I saw a line on my terminal right after the "at the end of at to cart method" message, which said :
"No template found for ShoppingExperiencesController#add_to_cart, rendering head :no_content".
so I don't really know what head :no_content is but i thought it might have un-do/save changes made to session by my method. so at the end of add_to_cart method i redirected to index page with
redirect_to '/'
still quite not sure why template not being found un-do my changes to hash, if anyone could share some light over this in the comments that'll be great! :)

Related

users names not showing in users view

Can anyone tell me why the email addresses are not showing in the users list view below?
<p id="notice"><%= notice %></p>
<h1>Users</h1>
<table>
<thead>
<tr>
<th>Email</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #users.each do |user| %>
<tr>
**<td><%= user.email %></td>**
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New User', new_user_path %>
I'm not familiar with seeing the two asterisks around the element. I'm thinking that might be messing something up. If you want to bold the user's email you could try something like <td><b><%= user.email %></b></td>.
Are you getting any errors anywhere?
If the asterisks are just there to help us see the line of code, and you say that you see the users (and their emails) in the db, I think it could be one of two other relatively minor things.
Whats your controller look like for this view? Are you passing #users to this view? You could try just dumping #users on the page to make sure that it's available.
Is the field on your User model that holds the email called email?

How to Show Sum of Column in Rails

I want to display the sum of a column name "money" in my model Earning.
In the rails console, I can easily get the sum I want Earning.sum(:money) and it shows the sum.
earnings_controller.rb
def index
#earnings = Earning.sum(:money)
end
index.html.erb
<p id="notice"><%= notice %></p>
<h1>Earnings</h1>
<table>
<thead>
<tr>
<th>Money</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #earnings.each do |earning| %>
<tr>
<td><%= earning.money %></td>
<td><%= link_to 'Show', earning %></td>
<td><%= link_to 'Edit', edit_earning_path(earning) %></td>
<td><%= link_to 'Destroy', earning, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Earning', new_earning_path %>
It keeps throwing this error
NoMethodError in Earnings#index
What I've tried so far
I am stumped. I've tried changing the index action to #earnings = earnings.sum(:money) and that gave me this error "NameError in EarningsController#index". I also saw a similar problem here but since I think the issue is in my index.html.erb, it didn't help much. As I said earlier the code works in the Rails Console.
Thank you in advance for any help.
So you are not using #earnings in a proper way, in your view you use earnings as a collecion of objects, but in controller #earnings are defined as a sum of money but you are not using it, if you really need this sum, you can set two instance variables fiest #earnings = Earning.all and the second one #money_sum = Earnings.sum(:money) and then you can display somewhere your sum as = #money_sum, then you can iterate by #earnings to create some linka in your view
It looks like you want to do something like this.
First in your controller you want to get all earnings records.
def index
#earnings = Earning.all
end
Then in your view you iterate over all #earnings and spit out earnings.money as single value for each of your record.
If you want to get total of all earnings somewhere, you can do #earnings.sum(:money), which will basically give you single value as total of all earnings - Earning.all.

undefined method `page_leads' for nil:NilClass

I've been banging my head against this for a while. I know it's a simple problem, and I've reviewed other code examples where I'm doing this successfully, but, I'm completely stumped.
I'm getting an error "undefined method `page_leads' for nil:NilClass" when I try to go to the "Show" page. On my landing_pages "show" page I'm trying to show the leads that came in via that page.
My show page code for this is:
<table class="table table-striped">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Score</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #landingpage.page_leads.each do |page_lead| %>
<tr>
<td><%= page_lead.fname %></td>
<td><%= page_lead.lname %></td>
<td><%= page_lead.score %></td>
<td><%= link_to 'Show', page_lead %></td>
<td><%= link_to 'Edit', edit_page_lead_path(page_lead) %></td>
<td><%= link_to 'Destroy', page_lead, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
My landing_page model has:
has_many :page_leads
My page_lead model has:
belongs_to :landing_page
My controller code for the "show" method for both landing_pages and page_lead is:
def show
#landing_page = LandingPage.all(landing_page_params)
end
On my page_leads table I have the "landing_page_id" field so I can associate the landing page to the lead.
Any ideas what I'm doing wrong?
Thanks in advance
Your controller action does not load any instance of a model. You expect it to load an instance of a LandingPage (usually the one in params[:id] for a show action). So your controller should assign it:
# `GET /landing_pages/:id`
def show
#landingpage = LandingPage.find( params[:id] )
end
It is because your #landingpage instance variable is not defined when you run that code.
Basically, in your controller's action, you should have something like:
def show
#landinpage = ... # insert your definition here
# rest of your controller's action
end

Update a time field dynamically when checking a checkbox in Rails & dynamically updating the DB without using a Submit button

I'm trying to do the following:
1) When a checkbox gets checked, I want the Time of Arrival box to be updated with the time when the checkbox got checked dynamically.
I don't want to be pressing a submit button or anything of that sort, it should be dynamic, via AJAX i guess.
My current code looks like this:
<table border="1">
<tr>
<td><b>Present</b></td>
<td><b>Student ID</b></td>
<td><b>First Name</b></td>
<td><b>Last Name</b></td>
<td><b>Time of Arrival</b></td>
</tr>
<% #register.student_registers.each do |student_register| %>
<tr>
<td><%= check_box_tag "student_registers_ids[#{student_register.id}]", student_register.id, student_register.present?%></td>
<td><%= student_register.student.university_id%></td>
<td><%= student_register.student.first_name.titlecase%></td>
<td><%= student_register.student.last_name.titlecase%></td>
<td><%= student_register.time_of_arrival %></td>
</tr>
<% end %>
</table>
2) The other thing I want to do is to update the record in the database, as soon as the Present checkbox gets checked, without having to press a Submit button. This will be done in the model#show page, not the model#edit page.
Any suggestions?
EDIT:
I changed the code around, but it still isn't working...
<table border="1">
<tr>
<td><b>Present</b></td>
<td><b>Student ID</b></td>
<td><b>First Name</b></td>
<td><b>Last Name</b></td>
<td><b>Time of Arrival</b></td>
</tr>
<% form_tag :remote => true %>
<% #register.student_registers.each do |student_register| %>
<tr>
<td><%= check_box_tag "student_registers_ids[#{student_register.id}]",
student_register.id, student_register.present?,
:disabled => false,
:onclick => 'popup ' %></td>
<td><%= label_tag 'UniversityId', student_register.student.university_id%></td>
<td><%= label_tag 'FirstName', student_register.student.first_name.titlecase%></td>
<td><%= label_tag 'LastName', student_register.student.last_name.titlecase%></td>
<td><%= label_tag student_register.time_of_arrival, nil, :class => 'TimeOfArrival'%> </td>
</tr>
<% end %>
</table>
<%= submit_tag "Save", :confirm => "You sure", :onclick => 'alert("Test")'%>
Please, anybody help....
Here's what I would do:
Designate a common CSS class for all the checkbox inputs (to be used as a jQuery selector later).
Create an empty <span>...</span> element with an id that encodes the student id (e.g., 'toa_1234') in the "Time of arrival" cell.
Use jQuery .change() and $.ajax() to send the message to the server.
Create a corresponding controller or action to process the AJAX POST and return the recorded (server-side) time.
On AJAX success, display the recorded server time and disable the checkbox (so it can't be clicked again).
HTML/ERB:
<td><%= check_box_tag "student_registers_ids[#{student_register.id}]",
student_register.id, false,
:class => 'student_present' %></td>
<td><%= student_register.student.university_id%></td>
<td><%= student_register.student.first_name.titlecase%></td>
<td><%= student_register.student.last_name.titlecase%></td>
<td><%= content_tag :span, student_register.time_of_arrival,
:id => "toa_#{student_register.student.id}" %></td>
JS/CoffeeScript:
$ ->
$('input[type="checkbox"].student_present').change (e) ->
checkbox = $(this)
student_id = checkbox.val()
$.ajax
url: '/register/present'
method: 'POST'
dataType: 'json'
data:
student_id: student_id
success: (data) ->
$("span#toa_#{student_id}").html(data['toa'])
checkbox.attr 'disabled', true
Controller/action:
def present
student_id = params['student_id']
# TODO: mark student present and save in database
recorded_toa = Time.now # TODO replace with actual time
render json: { student_id: student_id, toa: recorded_toa.strftime('%I:%M %P') }
end

Making a table row into a link in Rails

I am trying to make a row in a table link to the edit page. I know the links are being created, because I can print them out. I am close, but am missing something important. What do I change to make the link work properly?
<h1>Scouts</h1>
<p><%= button_to "Add a new Scout", new_scout_path, :method => :get %></p>
<div class="message-board">
<table>
<tr>
<th>Name</th>
<th>Rank</th>
<th>Advancement Date</th>
<th>Age</th>
</tr>
<% #scouts.each do |scout| %>
<tr <% link_to edit_scout_path(scout) %> >
<td><%= scout.name %></td>
<td><%= scout.rank %></td>
<td><%= scout.advancement %></td>
<td><%= scout.age %></td>
</tr>
<% end %>
</table>
</div>
As Robin said, that's invalid HTML. You probably shouldn't do that.
I personally would put an onclick event on the tr using jQuery. The tr element would look like this:
<tr data-link="<%= edit_scout_path(scout) %>">
...
</tr>
And then the associated JavaScript (placed in a file such as app/assets/javascripts/scouts.js) would be something like this:
$("tr[data-link]").click(function() {
window.location = $(this).data("link")
})
This would make all tr elements that have a data-link attribute act as if they were URLs in the most unobtrusive way I can think possible.
I am new on rails and I have the same problem and use the Ryan's advise with some changes that are following -
$("tr").click(function() {
window.location = $(this).data("link")
})
You have to use $(this).
Here is my take to make those links, remote: true
$("tr[data-link]").click(function () {
$.ajax({
url: this.getAttribute('data-link'),
dataType: "script",
type: "GET"
});
event.preventDefault();
});
Simple Solution: add a link into a table cell:
This doesn't answer your question, but it provides a solution to the problem you are likely really after: just add an edit link into a cell, rather than on the table row because having a link on the table row itself may lead to expected results for users. If they are clicking on it, they might not want to be led to an edit link.
Like my grandpa used to say: KISS - Keep It Simple Stupid
<% #scouts.each do |scout| %>
<tr>
<!-- Simply edit the scout -->
<td> <%= link_to edit_scout_path(scout), "Edit Scout" %> </td>
<td><%= scout.name %></td>
<td><%= scout.rank %></td>
<td><%= scout.advancement %></td>
<td><%= scout.age %></td>
</tr>

Resources