how to stop cache from interfering with application logic - ruby-on-rails

I'm trying to use Rails 4 cache digests in my app, but am finding that it interferes with a lot of application logic. For example, in this code, the links that are supposed to only be revealed where the current_user's id matches #user.id aren't working properly when I have the cache surrounding the code. Those links are visible to anyone who views the page.
<% cache #languages do %>
<% for language in #languages%>
<tr>
<td><%= language.name %> </td>
<% if current_user && current_user.id == #user.id %>
<td><%= link_to "edit", {:controller => 'lawyer_profiles', :action =>'show', :language_id =>"#{language.id}"}, {:class => "editarea #{language.id}"}%></td>
<td><%= link_to "destroy", language, :confirm => 'Are you sure?', :method => :delete %></td>
<% end %>
</tr>
<% end %>
<% end %>
In this code, the cache was interfering with the #question instance variable. For example, due to the presence of the cache, when I clicked on the link to "Add An Answer," it had my answering a different #question than the one I should have been answering, because the cache kept a memory of the instance variable on a page that I had already navigated away from.
<% cache #answers do %>
<% if #answers.empty? %>
<div class="row">
<h5>This question hasn't been answered yet: <% if can? :create, #answer %>
<% if current_user && !current_user.answers.map(&:question_id).include?(#question.id) %>
<%= link_to "Add an answer", new_question_answer_path(#question) %>
<% end %>
<% end %> </h5>
....some code not included
How can I stop the cache from interfering with logic like this?

You'll have to add the logic into the cache key.
So...
cache [#answers, current_user.answers.map...]
This will base the view on what the user's answer is...you may want to break down the rest into more fragment caches in addition to the above.

Related

How do I add a delete function in my cart in rails?

the cart controller - im having trouble declaring the delete function
class CartController < ApplicationController
def add
id = params[:id]
cart = session[:cart] ||= {}
cart[id] = (cart[id] || 0) + 1
redirect_to :action => :index
end
def index
#cart = session[:cart] || {}
end
end
the main item page - the link to delete the item is already defined, I'm confused in the controller part
<h1 id="prodhead">Products</h1>
<table class="catalog">
<% for item in #items %>
<tr>
<td>
<div class="image">
<%= link_to (image_tag item.image_url), item %>
</div>
</td>
<td>
<div class="title">
<%= link_to item.title, item %>
</div>
<div class="description">
<%=h item.description %>
</div>
<div class="links">
<% if session[:login] == 1 %>
<%= link_to 'Edit Item', edit_item_path(item) %> |
***<%= link_to 'Delete Item', item, :confirm => 'Are you sure?', :method => :delete %>***
<% else %>
<%= link_to "Add to Cart", :controller => :cart, :action => :add, :id => item %><br />
<% end %>
</div>
<div class="price">
<%= number_to_currency(item.price, :unit => "&dollar;") %>
</div>
</td>
</tr>
<% end %>
</table>
<% if session[:login] == 1 %>
<p><%= link_to 'New item', new_item_path %></p>
<% end %>
The Routes.rb - the route for deleting is also defined already
OnlineShop::Application.routes.draw do
get "cart/index"
get "cart/add"
get "cart/checkout"
get "cart/del"
get "site/about"
get "site/contact"
get "user/admin_login"
get "user/logout"
resources :items
Well first of all I've notice you reposted your issue however this time somewhat more descriptive, please for future issues, think before you create a ticket and take the time to edit previous tickets which need refining to keep the community clean.
OT:
I see you've created item and cart resources with basic CRUD functionality however the way you did it is not quite "The rails way" I suggest you start a project bij using the scaffold command to learn how this CRUD and routes should be implemented.
If you are willing to learn more about the topic I advice reading: http://guides.rubyonrails.org/getting_started.html
Also I've noticed you use the "h" syntax to escape your output this is only done before Rails 2.3.8 may I suggest using a newer rails version when starting out?

How to create multi checkboxes and attach them to controller action like Edit or Delete?

I have created a scaffold Phone and index.html.erb shows a simple table with list of phone and edit/delete options. Now i want to add jquery checkboxes so I can do bulk delete or move actions. See attached image here
Can someone give me any idea/pointers on how to do it ?
Edit - this is the index.html.erb file
<% #phones.each do |phone| %>
<tr>
<td><%= phone.model %></td -->
<td><%= phone.type %></td>
</tr>
<% end %>
there is no form here so I am not sure I can use form_tag helpers or am I confusing something ?
Thanks
This would be a starting point, a form with the check boxes.
<%= form_tag(:controller => "phone", :action => "bulk_update", :method => "PUT") %>
<%= check_box_tag(:blackberry) %>
<%= label_tag(:pet_dog, "Blackberry") %>
<%= check_box_tag(:Nokia) %>
<%= label_tag(:pet_cat, "Nokia") %>
<%= submit_tag("Update") %>
<% end %>
Then a controller action called bulk_update and you could delete/update the records based on what has been submitted.
EDIT: You will also want to create a route in routes.rb for this.
Wrap the table in a form helper.
<%= form_tag foo_path do %>
# ...
<% #phones.each do |phone| %>
<tr>
<td><%= check_box_tag "selected[]", phone.id %></td>
<td><%= phone.model %></td>
<td><%= phone.type %></td>
</tr>
<% end %>
# ...
<%= button_tag "Do something" %>
<% end %>
This creates a form, with a checkbox in every row of the table. Replace foo_path with the route helper that you want to use. The value of the selected checkboxes will be passed to your controller action in the array params[:selected], where you can do with them as you wish. The values of each checkbox will be the id for the corresponding phone object.

Link_to another view ruby on rails

I am trying to use the link_to feature to link one view to another.
The view i am calling link_to is app/views/instructors/show.html.erb and that snippet of code looks like this (namely, the second to last line of it)
<% provide(:title, #instructor.login) %>
<% courses = Course.where(:instructor_ID => #instructor.id) %>
<div class="span2">
<h1 align=center ><%= #instructor.login %></h1>
<%= link_to "Add course", new_course_path(:instructor_ID\
=> #instructor.id), :class => "btn" %>
<br>
<br>
<%= link_to "Remove course", delete_course_path(courses), :class => "btn"%>
</div>
The view I am trying to link to is is app/views/courses/show_all.html.erb and looks like this:
<% #courses.each do |course| %>
<tr>
<td><%= course.course_name %></td>
<td><%= course.instructor_ID %></td>
<td><%= link_to 'Show', course %></td>
<td><%= link_to 'Edit', edit_course_path(course) %></td>
<td><%= link_to 'Destroy', course, :method => :delete, :data => { :confirm => 'Are you sure?' } %></td>
</tr>
delete_course_path routes to app/views/courses/show_all.html.erb shown above. When I try the code above, I get the following error:
undefined method `each' for nil:NilClass
At this line:
<% #courses.each do |course| %>
Any ideas what i'm missing in my link_to?
In your show_all action, you should define a #courses instance variables. This is
<% courses = Course.where(:instructor_ID => #instructor.id) %>
not passed to show_all.html.erb.
An instance variables is a variable passed from action of controller to the view corresponding.
I suppose when you show page of instructor, your route will like this: /instructors/:id, so maybe in your show_all action of instructor controller, you need something like:
def show_all
#courses = Course.where(instructor_ID: params[:id])
render 'courses/show_all'
end
This means that #courses is nil. Did you set it in your show_all action of your controller? E.g.
def show_all
#courses = Course.all
end
Also, in your show view, you set courses to a collection of Course objects, but your "Remove course" link looks like you only want to delete one course. Why do you use the delete_course route to link to your show_all view?

searching from the main page in Rails

I am working on my first web and Rails app and can not figure out how to get a search feature work from my main page to one of the controllers.
How to send the request and redirect to a results page to show the results from the search.
I can't get this to work as am not sure how to route in a way my variable #histories will keep results and display on the show page.
I would appreciate some insight into search from any page and displaying results on a dedicated page.
Here is what i have so far in terms of the controller, model and partials.
Shipments Model:
def self.search(search)
search_condition = search
find_by_sql("SELECT cargo_transit_histories.current_location,cargo_transit_histories.updated_at FROM cargo_transit_histories
INNER JOIN shipments ON shipments.id = cargo_transit_histories.shipment_id WHERE shipments.tracking_number='search_condition'")
end
Tracking Controller:
def search
#histories = Shipment.search(params[:search])
render('show')
end
Show (Found in Tracking view):
<div class="search_result">
<%= render 'track/search_results' %>
</div>
_search (partial):
<%= form_tag :controller => 'tracking', :action => 'search', :method => 'get' do %>
<%= text_field_tag :search, params[:search], :id => 'search_field' %>
<%= submit_tag "Search", :name => nil %>
<%= link_to_function "Clear", "$('search_field').clear()" %>
<% end %>
_search_results (partial):
<div class="Results list">
<table class="Resultslisting" summary="Result list">
<tr class="header">
<th>Current Location</th>
<th>Date/Time</th>
</tr>
<% if !#histories.empty? %>
<% #histories.each do |result| %>
<tr>
<td><%= result.current_location %></td>
<td><%= result.updated_at %></td>
</tr>
<% end %>
</table>
<% else %>
<p> The tracking number does not exist!</p>
<% end %>
</div>
Try something like the following adapted example:
https://gist.github.com/4173716
But you need to dig a bit deeper into Rails 3 to understand why.

I am having trouble with my first project in ruby on rails

Here's my index action in the books controller: http://pastebin.com/XdtGRQKV
Here's the view for the action i just mentioned: http://pastebin.com/nQFy400m
Here's the result without being logged in: http://i.imgur.com/rQoiw.jpg
Here's the result when i'm logged in with the user 'admin': http://i.imgur.com/E1CUr.jpg
So the problem is that, in the view, before line 25 the 'user' variable seems to be empty ( or not loaded), and after line 25 the variable 'user' has the expected values.
I have tried initializing a variable in the index method of the books controller but get exactly the same results.
Thanks in advance!
BTW had to make the links text because of stackoverflow limit.
This:
user = User.find_by_id(session[:user_id])
should be in controller, not in view (MVC!) like this:
#user = User.find_by_id(session[:user_id])
Then in your view, as #Voyta answered, use <%= #user.username %>. Code inside <% %> is evaluated, but not rendered, so if you want to put result in your html, you need to add =.
And all yours if user and if user.admin == 1 would look much better this way:
<% if user %>
<td><%= link_to 'Show', book %></td>
<% if user.admin == 1 %>
<td><%= link_to 'Edit', edit_book_path(book) %></td>
<td><%= link_to 'Delete', book, :confirm => 'Are you sure?', :method => :delete %></td>
<% end
end
%>
If you use if in single line like here:
<%
if user
if user.admin == 1
%>
<%= link_to 'New book', new_book_path %>
<%
end
end
%>
You can write the same like this:
<%= link_to 'New book', new_book_path if user && user.admin == 1 %>
You didn't output user.username. It should be <%= user.username %>, not <% user.username %>

Resources