I am trying to get my app to pull all posts created on a specific date.
case meta_type
when "user"
#meta = User.find(params[:user_id])
#meta_title = #meta.username + "'s Posts"
#posts = Post.find(:all, :conditions => { :user_id => #meta.id})
when "category"
#meta = params[:category]
#meta_title = #meta + " Posts"
#posts = Post.find(:all, :conditions => { :category => #meta})
when "date"
#meta = Date.parse(params[:date])
#meta_title = #meta.strftime("%d/%m/%Y") + " Posts"
#posts = Post.find(:all, :conditions => { :created_at => #meta})
end
Here is my view:
- if #meta
%h2= #meta_title
- if #posts.count > 0
- #posts.each_slice(2) do |slice|
.row
- slice.each do |post|
.col-sm-6
.blog_entry
.img
%h3
%a= link_to post.title, posts_path + '/' + post.id.to_s
= render "blog_meta", :post => post
- else
%p= #user.username + " has no posts."
- else
%h2= "User does not exist."
I am getting undefined method 'username' for nil:NilClass which in itself isn't a problem, but the fact that it is getting filtered through to the else statement is, because it should be finding posts for that date.
Also I just realised by passing through the datetime, it will actually be looking for posts created at the exact same time, whereas I would like it to pull up all posts created on the day, not the time.
Any suggestions?
Thanks
So, ignoring the subtleties of exactly which time zone you're evaluating the date in, you can change your when "date" block to read as follows
#meta = Date.parse(params[:date])
#meta_title = #meta.strftime("%d/%m/%Y") + " Posts"
beginning_of_day = #meta.to_datetime.beginning_of_day
end_of_day = #meta.to_datetime.end_of_day
#posts = Post.where("created_at >= ?", beginning_of_day).where("created_at < ?", end_of_day).order(:created_at).all
That will give you a list of Posts created on the day in question, in the time zone in which your app is running, ordered by creation time.
You can make a number of other adjustments (changing sort order, using a different time zone, etc.) as needed.
Related
I am creating a form for my posts search. I am doing like this ....
erb form code...
<%= form_tag '/posts/search-post', :remote=> "true" do %>
<p>
<%= text_field_tag :search, params[:search], :placeholder => "Search Posts..." %><br/>
<%= radio_button_tag :day, 1, params[:day] %>None
<%= radio_button_tag :day, 2, params[:day] %>Last Week
<%= radio_button_tag :day, 3, params[:day] %>Last Month<br/>
<%= submit_tag "Search", :onclick => "document.getElementById('spinner').style.visibility='visible';document.getElementById('postlist').style.visibility='hidden'" %>
</p>
<% end %>
root.rb
match 'posts/search-post', to: 'posts#search_post'
posts_controller.rb
def search_post
if !params[:search].blank? && params[:day].blank?
#posts = Post.paginate(page: params[:page],:per_page => 5).search(params[:search])
elsif params[:search].blank? && !params[:day].blank?
#posts = Post.paginate(page: params[:page],:per_page => 5).all if params[:day] == "1"
#posts = Post.paginate(page: params[:page],:per_page => 5).where("created_at >= ?", 1.week.ago.utc) if params[:day] == "2"
#posts = Post.paginate(page: params[:page],:per_page => 5).where("created_at >= ?", 1.month.ago.utc) if params[:day] == "3"
elsif !params[:search].blank? && !params[:day].blank?
#posts = Post.paginate(page: params[:page],:per_page => 5).search(params[:search]) if params[:day] == "1"
#posts = Post.paginate(page: params[:page],:per_page => 5).search(params[:search]).where("created_at >= ?", 1.week.ago.utc) if params[:day] == "2"
#posts = Post.paginate(page: params[:page],:per_page => 5).search(params[:search]).where("created_at >= ?", 1.month.ago.utc) if params[:day] == "3"
else
end
end
Post.rb model
def self.search(search)
search_condition = "%" + search + "%"
if search
find(:all, :conditions => ['lower(content) LIKE ? OR lower(title) LIKE ?', search_condition.downcase,search_condition.downcase])
else
find(:all)
end
end
search-post.js.erb
$("#posts_list").html("<%= escape_javascript( render(:partial => "posts") ) %>");
When I search by both keyword and day type then searching is not working (Getting all post list-items). I don't know where i am wrong. Please help.
I am not sure if you've done this intentionally, but in both your elseif and else sections in your controller, you're overwriting your search results.
For example, in your else section, you first do this:
#posts = Post.paginate(page: params[:page],:per_page => 5).search(params[:search]) if params[:day] == "1"
and then you do this:
#posts = Post.paginate(page: params[:page],:per_page => 5).where("created_at >= ?", 1.week.ago.utc) if params[:day] == "2"
Which means that the second set of results that are saved in #posts will overwrite your first set of results (what was saved in #posts in your first line).
Since you're doing an "&&" operation, then you should include your result set from your first line into the second.
One solution to your problem might be to change your Post.rb model to something like this:
def self.search(search, previous_results_set)
search_condition = "%" + search + "%"
if search
if previous_result_set.nil?
find(:all, :conditions => ['lower(content) LIKE ? OR lower(title) LIKE ?', search_condition.downcase,search_condition.downcase])
else
previous_result_set.find(:all, :conditions => ['lower(content) LIKE ? OR lower(title) LIKE ?', search_condition.downcase,search_condition.downcase])
else
find(:all)
end
end
My code might not be perfect and you can probably find a more efficient way of doing it in your code, but you get the idea. Even when you user the .where, you need to perform the .where on the previous result set, not on the Post model as a whole again. That way you will be filtering your previously filtered results.
Hope this helps.
After updating to rails 3.2.11, I noticed a problem with a search form in my app. After seeing the "We're sorry, but something went wrong." message on Heroku, I checked the logs and noticed the error message below:
NoMethodError (undefined method `to_i' for ["2010"]:Array):
app/controllers/skis_controller.rb:29:in `index'
This is referring to the index controller, where my search results are displayed. Im using a search form partial for the actual search form, which contains several collection_selects.
Line 29 in the index action refers to the model_year ("2010" in the search above). When I remove the model_year field from the collection_select everything works fine (no error message after searching). This is what the model_year collection_select looks like:
<%= collection_select(:ski, :model_year, #model_years.sort_by(&:model_year).reverse, :model_year, :model_year, {}, :multiple => true, :class => "chzn-select", :'data-placeholder' => "Enter Model Year") %>
This is bugging me because it has been working fine for the last three weeks. I recently updated to rails 3.2.11 but I'm not positive that is when the problem started (I know I did not notice it before). I checked out the collection_select documentation and everything seems fine.
model_year is stored in the database as an integer and I've confirmed this with rails console.
Any help or ideas would be very much appreciated! Thanks
EDIT - UPDATED to add controller code:
def index
#companies = Brand.scoped
#ski_types = Ski.find(:all, :select => "DISTINCT ski_type")
#genders = Ski.find(:all, :select => "DISTINCT gender")
#names = Ski.find(:all, :select => "DISTINCT name")
#price_ranges = PriceRange.scoped
#model_years = Ski.find(:all, :select => "DISTINCT model_year")
#sorts = ["Price", "Rating", "Availability"]
if params[:ski].present? || params[:brand].present? || params[:price_range].present?
# Creates references for collection select
ski_type = params[:ski][:ski_type].reject(&:blank?)
gender = params[:ski][:gender].reject(&:blank?)
company = params[:brand][:company].reject(&:blank?)
name = params[:ski][:name].reject(&:blank?)
price_range = params[:price_range][:price_range]
model_year = params[:ski][:model_year].reject(&:blank?)
# raise ski_type.any?.inspect
#ski = Ski.new
#ski.ski_type = ski_type
#ski.gender = gender
#ski.name = name
#ski.model_year = model_year
#price_range = PriceRange.new
#price_range.price_range = price_range
#brand = Brand.new
#brand.company = company
skis = Inventory.search_price(price_range)
skis_refined = Ski.search_characteristics(ski_type, gender, company, name, model_year)
ski_ids2 = skis.map(&:id) & skis_refined.map(&:id)
#all_skis = Ski.where(:id => ski_ids2)
if params[:sort_by] == "Price Low to High"
#overlapping_skis = Kaminari.paginate_array(#all_skis.joins(:inventories).order("inventories.price ASC").uniq_by(&:id)).page(params[:page]).per(30)
elsif params[:sort_by] == "Price High to Low"
#overlapping_skis = Kaminari.paginate_array(#all_skis.joins(:inventories).order("inventories.price DESC").uniq_by(&:id)).page(params[:page]).per(30)
elsif params[:sort_by] == "Rating"
#overlapping_skis = Kaminari.paginate_array(#all_skis.joins(:reviews).order("reviews.average_review DESC").uniq_by(&:id)).page(params[:page]).per(30)
else
#overlapping_skis = #all_skis.joins(:brand).order("brands.company ASC, skis.model_year DESC, skis.name ASC").page(params[:page])
end
else
#overlapping_skis = Ski.joins(:brand).order("brands.company ASC, skis.model_year DESC, skis.name ASC").page(params[:page])
end
respond_to do |format|
format.html # index.html.erb
format.json { render json: #skis }
end
end
Updated for search method:
def self.search_characteristics(ski_type, gender, company, name, model_year)
#skis = Ski.scoped
if ski_type.any?
#skis = #skis.where(:ski_type => ski_type)
end
if gender.any?
#skis = #skis.where(:gender => gender)
end
if company.any?
brand_object = Brand.where(:company => company)
#id_array = brand_object.map(&:id)
#skis = #skis.where(:brand_id => #id_array)
end
if name.any?
#skis = #skis.where(:name => name)
end
if model_year.any?
#skis = #skis.where(:model_year => model_year)
end
return #skis
end
You have :multiple => true, meaning there can be multiple selected values for model_year, which is why it's an array. You'll have to handle those multiple values some way or remove :multiple => true.
I'm trying to make report page, on which user will choose start and end date and push buttopn report. Then hidden div became visible.
My search isn't on partial.
I am using jquery_datepicker so here is my code from view:
<%= form_tag(:controller => "financial_reports", :action => "index", :method => "post")%>
<%= datepicker_input "financial_report","start_date", :dateFormat => "dd/mm/yy" %>
<%= datepicker_input "financial_report","end_date", :dateFormat => "dd/mm/yy" %>
<%= submit_tag "Run Report"%>
<% end %>
Here is my code from controller:
def search
#financial_reports = current_user.financial_reports.search(params[:start_date], params[:end_date]
render :index
end
In my Model:
def self.search(from,to)
find(:all, :conditions => [ "BETWEEN ? AND ?", from, to])
end
And it gives me error:
ActiveRecord::StatementInvalid in FinancialReportsController#search
SELECT `financial_reports`.* FROM `financial_reports` WHERE `financial_reports`.`user_id` = 67 AND (BETWEEN NULL AND NULL)
and below this:
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"AMobLLRV3aAlNn6b4Au+1nRP2AN1TLQcBCytBXhDA/g=",
"type"=>"",
"financial_report"=>{"start_date"=>"05/08/2012",
"end_date"=>"11/08/2012"},
"commit"=>"Run Report",
"method"=>"post"}
Where is my error ?
If both parameters are set at all times, you can use:
#financial_reports = current_user.financial_reports.where(:created_at => ((params[:start_date].to_date)..(params[:end_date].to_date))
If that's not the case, you could (for example) do this:
#financial_reports = current_user.financial_reports
if params[:start_date].present?
#financial_reports = current_user.financial_reports.where("created_at >= ?", params[:start_date])
end
if params[:end_date].present?
#financial_reports = current_user.financial_reports.where("created_at <= ?", params[:end_date])
end
You will probably want to encapsulate this in scopes.
I have this terribly large controller in my app. I'd really like to make it as skinny as possible. Below is some of the code, showing the types of things I'm currently doing.. I'm wondering what things I can move out of this?
A note - this is not my exact code, a lot of it is similar. Essentially every instance variable is used in the views - which is why I dont understand how to put the logic in the models? Can models return the values for instance variables?
def mine
#For Pusher
#push_ch = "#{current_user.company.id}"+"#{current_user.id}"+"#{current_user.profile.id}"
#Creating a limit for how many items to show on the page
#limit = 10
if params[:limit].to_i >= 10
#limit = #limit + params[:limit].to_i
end
#Setting page location
#ploc="mine"
#yourTeam = User.where(:company_id => current_user.company.id)
#Set the user from the param
if params[:user]
#selectedUser = #yourTeam.find_by_id(params[:user])
end
#Get all of the user tags
#tags = Tag.where(:user_id => current_user.id)
#Load the user's views
#views = View.where(:user_id => current_user.id)
if !params[:inbox]
#Hitting the DB just once for all the posts
#main_posts = Post.where(:company_id => current_user.company.id).includes(:status).includes(:views)
#main_posts.group_by(&:status).each do |status, posts|
if status.id == #status.id
if #posts_count == nil
#posts_count = posts
else
#posts_count = #posts_count + posts
end
elsif status.id == #status_act.id
if #posts_count == nil
#posts_count = posts
else
#posts_count = #posts_count + posts
end
end
end
if params[:status] == "All" || params[:status] == nil
#posts = Post.search(params[:search]).status_filter(params[:status]).user_filter(params[:user]).order(sort_column + " " + sort_direction).where(:company_id => current_user.company.id, :status_id => [#status.id, #status_act.id, #status_def.id, #status_dep.id, #status_up.id]).limit(#limit).includes(:views)
else
#posts = Post.search(params[:search]).status_filter(params[:status]).user_filter(params[:user]).order(sort_column + " " + sort_direction).where(:company_id => current_user.company.id).limit(#limit).includes(:views)
end
elsif params[:inbox] == "sent"
#yourcompanylist = User.where(:company_id => current_user.company.id).select(:id).map(&:id)
#yourcompany = []
#yourcompanylist.each do |user|
if user != current_user.id
#yourcompany=#yourcompany.concat([user])
end
end
if params[:t]=="all"
#posts = Post.search(params[:search]).status_filter(params[:status]).user_filter(params[:user]).tag_filter(params[:tag], current_user).order(sort_column + " " + sort_direction).where(:user_id => current_user.id).includes(:views, :tags).limit(#limit)
elsif params[:status]!="complete"
#posts = Post.search(params[:search]).status_filter(params[:status]).user_filter(params[:user]).tag_filter(params[:tag], current_user).order(sort_column + " " + sort_direction).where(:user_id => current_user.id).includes(:views, :tags).limit(#limit)
elsif params[:status]!=nil
#posts = Post.search(params[:search]).status_filter(params[:status]).user_filter(params[:user]).tag_filter(params[:tag], current_user).order(sort_column + " " + sort_direction).where(:user_id => current_user.id).includes(:views, :tags).limit(#limit)
end
end
respond_to do |format|
format.html # index.html.erb
format.js # index.html.erb
format.xml { render :xml => #posts }
end
end
You can start by moving logic into the model...
A line like this screams of feature envy:
#push_ch = "#{current_user.company.id}"+"#{current_user.id}"+"#{current_user.profile.id}"
I would recommend moving it into the model:
#user.rb
def to_pusher_identity
"#{self.company_id}#{self.id}#{self.profile_id}"
end
And then in your controller
#push_ch = current_user.to_pusher_identity
At this point you could even move this into a before_filter.
before_filter :supports_pusher, :only => :mine
Another thing you can do is create richer associations, so you can express:
#tags = Tag.where(:user_id => current_user.id)
as
#tags = current_user.tags
Another example would be for main posts, instead of
Post.where(:company_id => current_user.company.id).includes(:status).includes(:views)
you would go through the associations:
current_user.company.posts.includes(:status).includes(:views)
When I'm drying out a controller/action I try to identify what code could be (should be?) offloaded into the model or even a new module. I don't know enough about your application to really point to where these opportunities might lie, but that's where I'd start.
Few quick ideas:
Consider using respond_to/respond_with. This controller action can be splitted up to two separate ones - one for displaying #main_posts, another for params[:inbox] == "sent". The duplicate code can be removed using before_filters.
Also, a couple of gem suggestions:
use kaminari or will_paginate for pagination
meta_search for search and sorting
I have an index view that lists all of the tags for my Entry and Message models. I would like to only show the tags for Entries in this view. I'm using acts-as-taggable-on.
Tags Controller:
def index
#letter = params[:letter].blank? ? 'a' : params[:letter]
#tagged_entries = Tagging.find_all_by_taggable_type('Entry').map(&:taggable)
#title = "Tags"
if params[:letter] == '#'
#data = Tag.find(#tagged_entries, :conditions => ["name REGEXP ?",
"^[^a-z]"], :order => 'name', :select => "id, name")
else
#data = Tag.find(#tagged_entries, :conditions => ["name LIKE ?",
"#{params[:letter]}%"], :order => 'name', :select => "id, name")
end
respond_to do |format|
flash[:notice] = 'We are currently in Beta. You may experience errors.'
format.html
end
end
tags#index:
<% #data.each do |t| %>
<div class="tag"><%= link_to t.name.titleize, tag_path(t) %></div>
<% end %>
I want to show only the taggable type 'Entry' in the view.
Any ideas? Thank you for reading my question.
SECOND EDIT:
Tags Controller:
def index
#title = "Tags"
#letter = params[:letter].blank? ? 'a' : params[:letter]
#taggings = Tagging.find_all_by_taggable_type('Entry', :include => [:tag, :taggable])
#tags = #taggings.map(&:tag).sort_by(&:name).uniq
#tagged_entries = #taggings.map(&:taggable)#.sort_by(&:id)#or whatever
if params[:letter] == '#'
#data = Tag.find(#tags, :conditions => ["name REGEXP ?",
"^[^a-z]"], :order => 'name', :select => "id, name")
else
#data = Tag.find(#tags, :conditions => ["name LIKE ?",
"#{params[:letter]}%"], :order => 'name', :select => "id, name")
end
respond_to do |format|
format.html
end
end
tags#index:
<% #data.each do |t| %>
<div class="tag"><%= link_to t.name.titleize, tag_path(t) %></div>
<% end %>
Max Williams' code works except when I click on my alphabetical pagination links. The error I'm getting [after I clicked on the G link of the alphabetical pagination] reads:
Couldn't find all Tags with IDs (77,130,115,...) AND (name LIKE 'G%') (found 9 results, but was looking for 129)
Can anyone point me in the right direction?
#taggings = Tagging.find_all_by_taggable_type('Entry', :include => [:tag, :taggable])
#tags = #taggings.map(&:tag).sort_by(&:name)
#tagged_entries = #taggings.map(&:taggable).sort_by(&:id)#or whatever