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
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 => "$") %>
</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?
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.
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?
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.
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 %>