Click count the link article in rails - ruby-on-rails

I have view
<% #r.each do |g| %>
<%= link_to g.title %>
<% end %>
When I click the link i won't to display the count how many people's click this link.
Like this:
<%= link_to g.title %> Click:<%= countclick %>
Title Click:45

Article should have countclicks:integer database column.
Than in article show method (I think you use this method to show article):
def show
#article = Article.find(params[:id])
count=#article.countclicks+1
#article.update_attributes(:countclicks=> count)
#other code
end
And than in index view:
<% #articles.each do |article| %>
<%= link_to "#{article.name}", show_article_path(article)%>
<%=article.countclick %>
<% end %>
Or alternatively you can do this via model callbacks.

If you want to use link_to like this, you have to give it a block:
<% link_to g.title do %>
Click <%= countclick %>
<% end %>

Related

conditional in users/show page to display info or not based users having created it

This is the error I get:
Showing /home/ubuntu/workspace/UMUV/app/views/users/show.html.erb where line #6 >>raised:
undefined method `name' for nil:NilClass
This is my conditional in users/show:
<% if #profile_info.present? %>
<%= #profile_info.region.name %>
<% else %>
<%= #user.email%>
<% end %>
This is in the users/controller:
def show
#user = User.find(params[:id])
#profile_info = Profile.find_or_initialize_by(user_id: params[:id])
end
I basically want to know how to not have an error when i visit a user's profile page and the user hasn't updated their profile yet. Showing the page is working fine if i update the user's profile through "edit page" manually.
Please help with the conditional. I also have a feeling i can create method in user.rb or users/controller, but really dont know how to implement this conditional to do what i want it to.
Thank you
In your show page you can replace this :
<% if #profile_info.present? %>
<%= #profile_info.region.name %>
<% else %>
<%= #user.email%>
<% end %>
with this:
<% if #profile_info.present? %>
<%= #profile_info.region.try(:name) %>
<% else %>
<%= #user.try(:email)%>
<% end %>
and also go through this post: http://everydayrails.com/2011/04/28/rails-try-method.html
Well you can always test an initalized object vs a saved object using new_record? -- which would make your above view look more like:
<% if #profile_info.new_record? %>
<%= #user.email%>
<% else %>
<%= #profile_info.region.name %>
<% end %>
also you might be able to take advantage of try on part of your page, which fails gracefully if an attribute doesn't exist, like
#profile_info.region.try(:name)
Since your error is with the name #profile_info.region.name not being present you could change your conditional to:
<% if #profile_info.region.name.present? %>
<%= #profile_info.region.name %>
<% else %>
<%= #user.email%>
<% end %>
Or if you really want to test #profile_info.present? you could nest conditionals like this:
<% if #profile_info.present? %>
<% if #profile_info.region.name.present? %>
<%= #profile_info.region.name %>
<% end %>
<% else %>
<%= #user.email%>
<% end %>
I hope that helps!

How to redirect to the same page with custom params using search form?

I have a page (get 'records/:id' => 'records#show', as: 'show_record'), with a long list of records of table "Page". I would like to be able to refine this list based on entered params. How can I add params to the end of the current url using a search form?
To illustrate:
<!--tentative search form
<%= form_tag show_record_path(#record), :method => :get do %>
<%= text_field_tag :search, params[:x] %>
<%= submit_tag "search" %>
<% end %>
-->
<!--set filter-->
<% if params[:x].nil? %>
<% #pages = #record.pages %>
<% else %>
<% #pages = #record.pages.where("name LIKE ?", params[:x]) %>
<% end %>
<!--list-->
<% #pages.each do |page| %>
<%= page.name %>
<% end %>
In your illustration you're suggesting doing this logic in the view. I would suggest doing any filtering in your controller. I would suggest having a look at this RailsCast. This one is also very good.

Best way to define global objects in Ruby on Rails

I have an app that has two models Category and Product
Products belong to categories.
I have created a navbar dropdown that requires an #category and #product object to be available across the entire app (the navbar is shown on every page of the application.)
What I can't work out is the best place to put these basic definitions without defining them multiple times in every page definition.
I need to define the following:
#category = Category.all
#products = #category.products.all
The navbar loop will then look something like this.
<% #category.each do |c| %>
<%= c.name %>
<% #products.each do |p| %>
<% link_to product_path(p) do %>
<%= p.name %>
<% end %>
<% end %>
<% end %>
I am a bit of a rails newbie so I am sure there are some errors in here but any help would be much appreciated!
If you need them in every single page of app, you can set them in ApplicationController's before_filter:
class ApplicationController
before_filter :get_categories
# ...
private
def get_categories
#categories = Category.includes(:products)
end
end
then, you can write in your view:
<% #categories.each do |category| %>
<%= category.name %>
<% category.products.each do |product| %>
<%= link_to p.name, p %>
<% end %>
<% end %>
I also fixed some other errors and convention incompatibilities.
The following code is incorrect.
#category = Category.all
#products = #category.products.all
This code assigns to #categories all the categories, then it attempts to fetch the products. It will not work, unless you have defined a products class method in the Category model. But I don't think so, otherwise you will just have to call Product.all.
Moreover, in the code below, you are trying to display the list of products per category, which definitely don't work with the two assignments before. According to what you are trying to achieve, you can't pre-assign the #products, because you want the products for a specific category.
Let's inline everything into the code.
<% Category.all.each do |category| %>
<%= category.name %>
<% category.products.each do |product| %>
<%= link_to product_path(product) do %>
<%= product.name %>
<% end %>
<% end %>
<% end %>
Next step is to make the code a little bit more performant, giving you need it everywhere.
<% Category.select(:id, :name).each do |category| %>
<%= category.name %>
<% category.products.select(:id, :name).each do |product| %>
<%= link_to product_path(product) do %>
<%= product.name %>
<% end %>
<% end %>
<% end %>
You could use pluck, but it will return an array and it will require a little bit more manipulation. However, it's way more performant.
<% Category.pluck(:id, :name).each do |category_id, category_name| %>
<%= category_name %>
<% Product.where(category_id: category_id).pluck(:id, :name).each do |product_id, product_name| %>
<%= link_to product_name, product_path(id: product_id) %>
<% end %>
<% end %>
It's not a good idea to chain all those methods inside a view, let's extract some code into the model.
class Category
def self.simple_listing
order(:name).pluck(:id, :name)
end
end
class Product
def self.simple_category_listing(category_id)
where(category_id: category_id).order(:name).pluck(:id, :name)
end
end
<% Category.simple_listing.each do |category_id, category_name| %>
<%= category_name %>
<% Product.simple_category_listing(category_id).each do |product_id, product_name| %>
<%= link_to product_name, product_path(id: product_id) %>
<% end %>
<% end %>
You can leave all this code into the view, or extract it into a partial. You don't even need to add a controller before filter, or make it "global". The code is self-contained, does not pollute the name space with instance variables, and it can easily be placed whenever you need it.

Couldn't find Zone without an ID

just trying the link_to image_tag helper, and I can't get it to work.
Can someone please tell me whats wrong?
Controller
class PagesController < ApplicationController
def home
#categories = Category.all
#zone = Zone.find(params[:id])
#zones = Zone.all
#photos = Photo.landing
end
end
View
<% #zones.limit(8).each do |zone| %>
<%= link_to image_tag "category-box_#{zone.id}.jpg", zone(zone.id) %>
<% end %>
Update
I found the Id problem came from the controller. Now the error is:
undefined method `symbolize_keys' for 1:Fixnum
Thanks!
You need to wrap your image_tag in brackets. Your code should look something like this:
<% #zones.limit(8).each do |zone| %>
<%= link_to image_tag("category-box_#{zone.id}.jpg"), spots_by_zone_path(zone.id) %>
<% end %>
OR
You can simply use block form of link_to
<% #zones.limit(8).each do |zone| %>
<%= link_to spots_by_zone_path(zone.id) do %>
<%= image_tag "category-box_#{zone.id}.jpg" %>
<% end %>
<% end %>

How do I check CanCan abilities on an object in a `shared/partial`?

Per the CanCan documentation, to check if a user has the ability to do something to any element in the view, you do something like this:
<% if can? :create, #project %>
<%= link_to "New Project", new_project_path %>
<% end %>
Or you can check with the class like:
<% if can? :create, Project %>
<%= link_to "New Project", new_project_path %>
<% end %>
In my case, I have a DashboardController#Index, that has this:
#nodes = current_user.nodes.where(:is_comment => nil)
In my views/dashboard/index.html.erb, I have this:
<% #nodes.each do |node| %>
<!-- Upload Video Comment Popup -->
<div class="box">
<%= render partial: "shared/comments", locals: {node: node} %>
</div>
<% end %> <!-- node -->
Then in my shared/_comments.html.erb, I have this:
<% if node.comments.present? %>
<% node.comments.each do |comment| %>
<% if can? :manage, Comment %>
Show Something Interesting Here
<% else %>
Show something boring here
<% end %>
<% end %>
<% end %>
That doesn't work.
I also tried this:
<% if node.comments.present? %>
<% node.comments.each do |comment| %>
<% if can? :manage, comment %>
Show Something Interesting Here
<% else %>
Show something boring here
<% end %>
<% end %>
<% end %>
And that doesn't work either.
This is my ability.rb
can :manage, Comment, user_id: user.id
I thought about creating a #comments instance variable in the controller, but the issue with that is that the comments are on a collection of nodes (i.e. I need to show multiple nodes, and each node has multiple comments).
How do I approach this?
Your last code should work after updating to CanCanCommunity version of cancan
<% if node.comments.present? %>
<% node.comments.each do |comment| %>
<% if can? :manage, comment %>
Show Something Interesting Here
<% else %>
Show something boring here
<% end %>
<% end %>
<% end %>
related to How do I show an error for unauthorized can can access

Resources