I'm using the rails gem kaminari (https://github.com/amatsuda/kaminari) in order to paginate my posts database. Currently I have the code #posts = Post.order('id').page(params[:page]).per(5) in my controller, but this orders the pages from earliest to most recent. How do I reverse this and order from most recent to earliest?
in your model you can do:
default_scope order("created_at DESC")
or
default_scope order("created_at ASC")
def index
#all = Model.all
#all = Model.order(sort_column + " " + sort_direction).paginate(:per_page => 5, :page => params[:page])
end
def sort_column
Model.column_names.include?(params[:sort]) ? params[:sort] : "updated_at"
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "DESC/ASC"
end
Related
first time poster. I am trying to sort a table of users using the Ransack gem and Kaminari for pagination. When I use name, id, etc. sorting works but when I try an association with posts_count, sorting breaks and won't work. Note: in the view, 'u.posts.count' work correctly. I have tried custom scopes in the users model, and creating custom objects for the search params but nothing seems to work. I think I am having trouble either in the default scope or the #search object not having the data. Need help!
Here are some relevant snippets:
models/user.rb
has_many :posts, :dependent => :destroy
models/post.rb
belongs_to :user
default_scope :order => 'post.created_at DESC'
controllers/users_controller.rb
def index
#title = "User Index"
#search = User.search(params[:q]) # Ransack
#total_users = User.all.count
# .per(10) is the per page for pagination (Kaminari).
#users = #search.result.order("updated_at DESC").page(params[:page]).per(10) #This displays the users that are in the search criteria, paginated.
end
views/users/index.html.erb
..
<%= sort_link #search, :posts_count, "No. of Posts" %> #Sort links at column headers
..
<% #users.each do |u| %> #Display everything in the table
<%= u.posts.count %>
<% end %>
You can add a scope to your User model:
def self.with_posts
joins(:posts).group('posts.id').select('users.*, count(posts.id) as posts_count')
end
and use it like this:
#search = User.with_posts.search(params[:q]) # Ransack
then, you can treat posts_count like any other attribute.
I found a solution:
Controller:
def index
sql = "users.*, (select count(posts.id) from posts\
where posts.user_id = users.id) as count"
#search = User.select(sql).search(params[:q])
if params[:q] && params[:q][:s].include?('count')
#users = #search.result.order(params[:q][:s])
else
#users = #search.result
end
.......
end
View:
<th><%= sort_link #search, :count, "posts count" %></th>
In model:
def self.get_by_slug(slug)
self.where("slug = ?", slug)
end
In controller:
#route: match '/category/:slug', :to => 'category#index', :as => "category_jobs"
#category = Category.get_by_slug(params[:slug])
#jobs = Job.where("category_id = ? AND expires_at > ?", #category.id, DateTime.now)
.paginate(:page => params[:page], :per_page => Jobeet::Application::MAX_JOBS_ON_CATEGORY_PAGE)
.order("expires_at desc")
When I trying get category.id in controller I am getting error:
undefined method `id' for #
Could somebody give me any advice?
If you expect a single record you should do:
#category = Category.get_by_slug(params[:slug]).first
because .where(something) doesn't return a single record.
#find the most recent news item for a specific locale
def self.find_most_recent_news_for_locale
first(:include => :news_item_detail,:conditions => ["news_items.created_at= ? AND news_item_details.locale = ?", maximum(:created_at), I18n.locale])
end
The Models
class NewsItem < ActiveRecord::Base
has_one :news_item_detail
end
class NewsItemDetail < ActiveRecord::Base
belongs_to :news_item
end
In Rails 3, you should use the where method for creating conditions:
def self.find_most_recent_news_for_locale
where("news_items.created_at = ? AND news_item_details.locale = ?",
maximum(:created_at),
I18n.locale).includes(:news_item_details).first
end
You might want to watch episode #202 of Railscasts as a quick tutorial.
I am trying to find any comments created after a datetime that were not made by the current user.
At first I did this..
current_user.comments.find(:all, :conditions=>["created_at > ? AND user_id != ?",
current_user.last_checked_mail, current_user])
but the problem here was that because it begins with the user model, its only finding comments exclusively made by that user.
So instead, I began searching for all comments associated with the user, and those comments children so long as their user_id is not the current_user
Comment.find(:all, :conditions => ["user_id = ?", current_user]).select { |c|
c.comments.find(:all, :conditions => ["user_id != ?", current_user])
}
But it seems that still draws every single comment related to the current_user, and not their children.
My Comment Model :
belongs_to :commentable, :polymorphic => true
has_many :comments, :as => :commentable
So you have a parent relation in your comment model? Use that!
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :parent, :class_name => "Comment"
def self.after(date)
where "created_at > ?", date
end
def self.replies_for(comments)
where :parent_id => comments.map(&:id)
end
def self.exclude_user(user_id)
where "user_id != ?", user_id
end
end
class User < ActiveRecord::Base
has_many :comments
def new_comments
comments.after(last_check_mail)
end
def new_responses
Comment.replies_for(new_comments).after(last_check_mail).exclude_user(id)
end
end
current_user.new_responses
PS. This is for Rails 3.
Try:
Comment.find(:all, :conditions => ["created_at > ? AND user_id != ?", current_user.last_checked_mail, current_user])
Try this:
Comment.all(:conditions => ["user_id != ? AND parent_id = ? AND created_at > ?",
current_user.id, current_user.id, current_user.last_checked_mail])
Better solution is to create a named_scope on the Comment model.
class Comment
named_scope :other_comments, lambda {|u| { :conditions =>
["user_id != ? AND parent_id = ? AND created_at > ?",
u.id, u.id, u.last_checked_mail ] }}
end
Now you can get others comments as:
Comment.other_comments(current_user)
Edit 1
Updated answer based for Polymorphic associations:
class Comment
def self.other_comments(u)
Comment.all(
:joins => "JOIN comments A
ON A.commentable_type = 'User' AND
A.commentable_id = #{u.id} AND
comments.commentable_type = 'Comment' AND
comments.commentable_id = A.id",
:conditions => ["comments.user_id != ? AND comments.created_at > ?",
u.id, u.last_checked_mail]
)
end
end
Now you can get others comments as:
Comment.other_comments(current_user)
I've a post model with act-as-taggable-on gem. Both tables have timestamps.
I started with
def tags
#posts = current_user.posts.find_tagged_with(params[:tag], :order => "#posts.tags.updated_at DESC"])
end
And when that didn't work, I tried changing things and ended up with this mess.
def tags
#posts = current_user.posts.find_tagged_with(params[:tag])
#tags = #posts.tags.all
#posts = #tags(params[:tag, :order => "#posts.tags.updated_at DESC"])
end
I basically want to sort by when the tags was last updated.
Bonus: Sort by tag.updated_at or post.updated_at, but in this particular app, I'll be updating tags the most, so just first one will be fine.
Any help is appreciated.
You have to join the tags table in your find statement:
def tags
#posts = Post.find_tagged_with(
params[:tag],
:conditions => {:user_id => current_user.id},
:joins => :tags,
:order => 'tags.updated_at DESC',
:group => 'posts.id'
)
end
Note: Find the right conditions to select only posts from the current user. This example could work, though.