I'm using acts_as_commentable_with_threading gem to make users able to comment my blog posts.
What I want to do now is to display most commented posts but I have no idea how to query them (and as far as I know, the gem not provides such method). Can you write me some tips or ideas how to achieve something like that?
Here is a method that I use to return the top users that have posted the most items. It may help you with your issue. I put this in the Application Helper because it is part of my side navigation bar and will be used on every page in the web application.
def top_posters
User.all(:select => "users.*, COUNT(user_id) as post_count",
:joins => "LEFT JOIN posts AS posts ON posts.user_id = users.id",
:group => "posts.user_id",
:order => "post_count DESC",
:limit => 5)
end
In my view, I have
<% top = top_posters() %>
<% for t in top %>
<li><%= link_to t.username, user_path(t) %>
(<%= t.posts.public_posts.count %>)</li>
<% end %>
For Rails 4+
You should use something like this:
Article.select("articles.*, COUNT(commentable_id) as comments_count")
.joins("LEFT JOIN comments AS comments ON comments.commentable_id = articles.id")
.group("comments.commentable_id")
.order("comments_count DESC")
.where("commentable_type = 'Article'")
.limit(5)
Related
I've just started programming in rails 3 days ago, learned ruby by the same time, and I'm having a hard time since yesterday figuring how to with one form, delete/update some of my instances, I only use one model "Task". Here's the code:
<%= form_for #task do |f| %>
<ul>
<% #tasks.each do |task| %>
<li id="task"><%= f.check_box :done %> <%= f.label :name %> </li>
<% end %>
<button onclick="doUpdate()">Mark Selected as done </button>
<%= button_to "Delete selected", :method => :delete %>
</ul>
<% end %>
Here's the controller:
def delete
#tasks = Task.find(:all, :conditions => ["task.done = ?", true])
#tasks.each do |task|
task.delete
end
#tasks = Task.all
end
My model have only 2 parameters. name:String and done:Boolean, I wan't to delete all the selected checkboxes. But this don't work for me
Thanks in advance.
The problem is, you are doing it wrong(and I'll tell you why). I could paste the code that would make it work but I'd rather explain, as you are probably doing it to learn.
Task.find(:all, :conditions => ["done = ?", true]) will return EVERYTHING in your database where done = true. You will be erasing everything that is marked as done in the DATABASE, not what were marked on the form. Task is your model, you can access the database by using find, where and other methods from activerecord(if activerecord doesn't sound natural to you, activerecord lets you get stuff from the database without the need of writing SQL queries).
What you really need to do in your controller is:
- You have to get what was sent from the form (check the documentation/web resources for the usage of param[] ).
- For every checkbox marked true, you erase a record. (you got the each part right, this is good!)
I don't think your view is right, I advise you to first be sure that the data that you receive is right(the params[]), then proceed to try to erase the record, or do whatever you want to do with it.
To "test" if your variables and code that is inside your controllers and models, use print #variable or something else(check rails docs how to debug).
I advise you use destroy instead of delete as other fellow stackoverflowers have said. Read the docs of destroy and delete.
Keep going :)
On a first glance, try using task.destroy instead of task.delete, and done instead of task.done See delete vs. destroy.
def destroy
#tasks = Task.find(:all, :conditions => ["done = ?", true])
#tasks.each do |task|
task.destroy
end
#tasks = Task.all
end
I am putting together a repository-type rails 3 site.
I have Thinking Sphinx installed and working on my site, insomuch as I can enter urls like localhost:3000/articles?search=test&page=2 and it will return the expected results.
I'm new to Rails (and web dev in general); I think I can manage the model and controller aspects of this, but the views so far have me stumped. I have a sidebar I would like to use as the search interface. The closest I have come is this (rendered as part of a sidebar partial):
<% form_tag #search, :method => :get do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search"%>
<% end %>
The search method is in my articles#index controller, and when I test it when the browser is pointed to that page (routed as /articles), it works as expected, but with this odd url: localhost:3000/articles?utf8=✓&search=test&commit=Search. When the browser is first pointed to the root path, nothing happens.
So, I think these are the main issues I need to address:
EDIT - solved (see below)
Should I move the search methods to their own controller, or should they be part of the articles controller? For now, Article will be the only model indexed.
EDIT - solved (see below)
Does anyone have any good example code of a faceted search view using Rails 3 and Thinking Sphinx? Like I said, I am something of a neophyte and am a little flustered by the documentation that skims by the view implementation. However, I am fairly adept at reading and interpreting code as long as it is reasonably complete.
Thanks in advance!
Solved:
How do I make the 'Search' button call the index method before trying to search? (I have solved this by replacing #search with articles_path).
Solved using will_paginate, which I had trouble with before, but which seems to be working now.
Hey,
This is an extract of how my site worked before i switched to solr
Product has many categories, we tell sphinx that we want to index them as facets
class Product < ActiveRecord::Base {
has_many :categorisations, :dependent => :destroy
has_many :categories, :through => :categorisations
define_index do
indexes product_name,
indexes description
indexes categories(:name), :as => :category,:facet => true
end
}
Results Controller
class ResultsController < ApplicationController
def index
#facets = Product.facets params[:qt], :conditions => {:category => params[:category}},:page => params[:page], :per_page => 20
#products = #facets.for
end
end
And then in the view you can do something like
<% #facets.each do |facet, facet_options| %>
<span><%= facet %></span>
<ul>
<% facet_options.each do |option, count| %>
<li><%= link_to "#{option} (#{count})",
:params => {facet => option, :page => 1} %></li>
<% end %>
</ul>
<% end %>
Hi I am having trouble trying to figure out how to implement a search form globally across my application. I have a series of posts that need to be searchable by users that are signed in and not signed in. I have added this code in my post model:
searchable do
text :content, :default_boost => 2
text :body, :default_boost => 1.5
end
However, I do not know where to go from there to create a search field across all pages and make it show the results I need. I am new to rails and would be happy to post more information if someone is willing to help me out.
First, you should add your search field like explained in this railscast: http://railscasts.com/episodes/37-simple-search-form
Since your search isn't specific to a particular model, use a generic controller name instead of ProjectsController though.
Then, you should replace the ActiveRecord finder by the use of the Sunspot DSL.
Here is an sample code to help get you started:
page = #page = params[:page] && params[:page].to_i || 1
#search = Sunspot.search(Realty) do # search_ids
per_page = params[:per_page] && params[:per_page].to_i || 10
# not adapted to your case
with(:equipments).all_of params['equip'].split(' ') if params['equip']
case params[:sort]
when "average_rating"
order_by :average_rating, :desc
when "type"
order_by :type, :asc
end
paginate :page => page, :per_page => per_page
# other criteria...
end
In your view, you can then iterate through #search.results
<%= will_paginate #search.results %>
<% #search.results.each do |hit| %>
<%# 'path' contains the stored polymorphic_path of each model object #%>
<% link_to hit.stored('path') do %>
<p><%= hit.stored('content') %></p>
<% end %>
<% end %>
Last, using WebSolR instead of a standard SolR server is quite simple, you can follow the setup instructions at https://github.com/onemorecloud/websolr-rails.
Edit:
As Nick commented, you should totally go to http://docs.heroku.com/websolr.
Thanks Nick !
I want to create a navigation system for my web application where there are several main categories for articles and several sub tags for each category.
For example, in category "Writing" there might be subcategories like "Essays," "Poetry" and "Fiction."
Each article would have a list of tags. If someone clicks the tag "Italy" on the fiction category show page I wouldn't want articles with the same tag of "Italy" from other categories like Essays or Poetry to appear on that page.
When a tag is clicked, the show page would be a category show page with a tag filter for all the articles with that particular tag in that category. It would not be a Tag show page.
Also, I'd like a sidebar with related tags. These would be tags that are in the same articles as those displayed on the category show page in descending order. I got related tags to work on the Tag page itself but not with the category constraint.
So far, I can get category pages and tag pages to work seperately, but I'd like to integrate the two.
I'm currently using Acts as Taggable on Steroids for the Tags and Acts as Tree for the categories.
Any ideas?
I think you are mixing two concepts here, a least in the question, perhaps not in your application. You have a category list modeled with acts_as_tree. That supports subcategories. The tags should not belong to subcategories. You want to filter by tag and category, more or less. You should be able to write simple queries that return lists of articles, such as:
#articles = Article.find(:all,
:include => "categories"
:conditions => ["(category_id = ? OR categories.parent_id = ?) AND tag_id = ?",
category_id, category_id, tag_id])
One more complex approach that I have used to do this is by doing faceted navigation with Solr. It supports combining these filters with full text search.
Matt, thanks a lot! This seems a lot simpler than what I had originally thought of.
However, my goal was to include subcategories in the navigation. The idea is that the parent categories would have everything in the subcategories and that if you clicked the sub categories it would narrow it down. I think that I'll check out Solr thought and see if it makes my code simpler.
After a bit of trial and error I got my code to work. It seems messy though. Any suggestions on simplification?
BTW some of these methods are defined through AATOS
In categories view#show:
<% for article in #articles %>
<%= link_to article.name, article %>
<% unless article.tag_list.empty? %>
<p class="tags">
Tags:
<%= render :partial => article.tags %>
</p>
<% end %>
And for the tag/navigation sidebar I have:
<% tag_cloud #tags, %w(css1 css2 css3 css4) do |tag, css_class| %>
<%= link_to tag, category_path(:filter => tag.name), :class => css_class %>
<% end %>
The category model, (not ideal but it works)
class Category < ActiveRecord::Base
acts_as_tree
has_many :articles
has_many :child_articles, :through => :children, :source => :articles
def grand_articles
children.map {|c| c.child_articles}.flatten.uniq
end
def to_param
name
end
def family
child_articles + articles + grand_articles
end
end
Finally the ugly controller code:
class CategoriesController < ApplicationController
def show
#category = Category.find_by_name(params[:id])
if (params[:filter]).nil?
#articles = #category.family
else
#articles = Article.find_tagged_with(params[:filter],
:conditions => ["articles.id IN (?)", #category.family])
end
#tags =
if (params[:filter]).nil?
Article.tag_counts :conditions => ["articles.id IN (?)", #category.family]
else
Article.find_related_tags(params[:filter],
:conditions => ["tags.id IN (?)", #category.family.map {|a| a.tags}.flatten.uniq])
end
It works but again it's ugly and brittle code. I'm sure I've committed some terrible sins here. Any suggestions for cleaning it up is appreciated.
I am new to rails so go easy. I have built my first blog and would like to set it up such that in the <% post.each do |post| %> render of the posts, I would like it to work such that it only displays 10 posts and then has a link to view the next 10.
I am hoping this is an easy question. Let me know if you would like me to post any code.
You should use the gem will_paginate.
The installation and usage is really easy: https://github.com/mislav/will_paginate/wiki/installation
Example usage: http://github.com/mislav/will_paginate
will_paginate is definitely the way to go, I just thought I'd add a link to a railscasts will_paginate video showing you how to use it since sometimes that can be an easier way to learn the basics than reading documentation. Plus you'll learn a brief history on how pagination used to be done when it was an included part of Rails (it was slower and more cumbersome). The old classic pagination has been moved out into it's own plugin too, but it's only recommended if you were already using it when you upgraded Rails to a version where they took it out.
Railscasts has a ton of other great videos that you might find helpful. For example, once you get more advanced you might want to try ajax pagination
Check out the will_paginate Gem.
It’s very easy to do pagination on ActiveRecord models:
#posts = Post.paginate :page => params[:page], :order => 'created_at DESC'
In the view, page links can be rendered with a single view helper:
<%= will_paginate #posts %>
I've got problems using "will_paginate", installing the GEM then unistalling... a REAL PROBLEM! So I decide to program the pagination on RoR, it was not difficult so I wanted to share what I did:
Controller:
def index
#how many register per page i want to show
#b = 30
#params via GET from URL
a = params[:page].to_i
#first register per page
a1 = params[:page].to_i * #b
#the query can be easy...
#callcenters = Income.all(:joins => "LEFT JOIN radcheck ON radcheck.id = incomes.radcheck_id", :order => "created_at DESC",:limit => "#{a1},#{#b}", :select => "radcheck.username as clave,caller_id, created_at, value")
#I need to know how many pages somehow
#registrostotales = Income.all(:joins => "LEFT JOIN radcheck ON radcheck.id = incomes.radcheck_id", :select => "radcheck.username as clave,caller_id, created_at, value").count
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #callcenters }
end
end
View:
...
Total de registros: <%= numero = #registrostotales %><br/><br/>
<!-- total pages -->
<% pages = #registrostotales / #b %>
<!-- the last page -->
<% if pages % #b > 0 %><% pages = pages + 1 %><% end %>
Paginas:
<% (0..(pages-1)).each do |i| %>
<!-- href or link_to, http://xxxxxxxx/yyyy?page=i -->
<%= link_to i+1, :action => "index", :controller => "callcenters", :page => i %>
<% end %>
<!-- the view.. -->
<table>
<tr>
<th>#</th>
<th>Teléfono (ID)</th>
<th>Zona</th>
</tr>
<% #callcenters.each do |callcenter| %>
<tr>
<td><%= numero - params[:page].to_i * 30 %><% numero = numero - 1 %></td>
<td><%= callcenter.caller_id %></td>
<td><%= Node.first(:conditions => {:calling_id => callcenter.caller_id}).description %></td>
</tr>
<% end %>
</table>
I hope this helps to someone!
We can do this with ease by using 'will_paginate-bootstrap' gem.
To continue firstly you add a line to the gem file as,
gem 'will_paginate-bootstrap'.
Now run bundle install.
In the controller, you will be using like #post = Post.all to get the
contents from models.
Instead use this
#post = Post.paginate(:page=>params[:page],per_page:5)
Here in the above line per_page field is to specify how many records you need
in a page.
In index.html.erb
At the end of the code i.e before ending the body tag
Add this,
<%= will_paginate #post,renderer: BootstrapPagination::Rails %>
Note: I thought Post as modal and post as variable declared in the controller.
Just go with your variables.
You can use the kaminari gem.
Very ease to use and highly customization friendly.
Adding pagination to a Ruby on Rails app
To add pagination to your Ruby on Rails app, you have to modify the following files:
Gemfile:
gem 'will_paginate', '~> 3.1.0'
gem 'will_paginate-bootstrap'
Areas controller --> index
#areas = Area.pagination_request(params[:page])
index.html.erb
<%= will_paginate #areas, renderer: BootstrapPagination::Rails %>
Model file:
def self.pagination_request(page)
paginate :per_page => 10, :page => page
end
Or, small, swifd & actively maintained: Pagy