How can I use .all for last 2 days in Rails3? - ruby-on-rails

I have a model called submission and currently I am displaying all the records in the database in the index page. In the submissions controller I have :
#submissions = Submission.all
However, now I only want the record for the past two days or the name field equals to some string, I tried this but it still shows all the records for me:
#submissions = Submission.all(:conditions => ["updated_at >= ? OR name = ?", 2.days.ago.to_date, "me"])
where updated_at and name are two fields in the submissions table.
Any idea where is wrong?
EDIT:
In my submission model:
attr_accessible :name, :updated_at

In Arel (Rails 3), your conditions should be in a where method, with (optionally) at the end, like so
Submission.where("updated_at >= ? OR name = ?", 2.days.ago.to_date, "me").all

Related

Rails Model Next/Prev Navigation Scope with datetime field

I have a model lets say Post which has a column called published_at (datetime). My model has two instance methods called next and prev.
I'm using mysql as a database adapter.
def next
self.class.unscope(:order).online
.where('published_at > ?', published_at)
.order('published_at ASC').first
end
def prev
self.class.unscope(:order).online
.where('published_at < ?', published_at)
.order('published_at DESC').first
end
With the code above the navigation works if every post has another date. If some posts are on the same date just one record of those gets shown.
Goal: Get the next or previous record ordered by published_at datetime column.
Any ideas?
Neither "next" , nor "previous" make sense in SQL. You have to explicitly define sort order by uniq key.
If you have non-uniq column as sort base, you have to add uniq one, id for example.
Then you have to change WHERE clause to accept rows wich have same value for your non-uniq column:
def next
condition = <<~SQL
(published_at = :published_at AND id > :id) OR
(published_at > :published_at)
SQL
self.class.unscope(:order).
online.
where(condition, published_at: published_at, id: id).
order(published_at: :asc, id: :asc).
take
end
prev is constructed similarly.

Selecting average and latest value of column on associated record using rails/activerecord

I have three models:
class Customer < ActiveRecord::Base
has_many :monthly_records
belongs_to :store
end
I need want to create an index view where I show the following fields:
customer.id
customer.name
store.name
average of monthly_records.grand total where monthly_records.month_start > ? AND monthly_records.month_start <= ?
monthly_records.grand_total for a specific month that the user will supply through the controller
Because this is an index and I want to show many rows at a time I want to do this in a single query and avoid the N+1 problem. I know how to do this with Customer.select.join.group if I take 1-3 and EITHER 4 or 5, but I can't figure out how to do all 5 at once.
I've found some pure SQL answers that look like they may work, but I'd prefer to keep this to activerecord if at all possible.
Using postgres 9.3.4 and rails 4.0.10.
Just guessing, Can you try:
Controller:
#customers = Customer.
select('customers.id,customers.name,monthly_records.grand_total,stores.name').
includes(:store, :monthly_records).
references(:stores, :monthly_records)
Try Customer\ to see if dot can start the next lines:
#customers = Customer\
.select('customers.id,customers.name,monthly_records.grand_total,stores.name')...
On view:
- #customers.each do |customer|
- records = customer.monthly_records.\
where('month_start > ? AND month_start <= ?', some_param,some_param)
= customer.id
= customer.name
= customer.store.name
= records.average(:grand_total)
= records.sum(:grand_total)
I think there is one set of records to be eager loaded (records variable). But this would be a start. Can you try? a let me know which tables have the N+1 problem with this approach.
Update: Eager loading monthly records for a given month
Rails gives you the possibility to eager load an association:
Model:
has_many :this_month_monthly_records,
->{ where('month_start > :start, month_start <= :start', start: your_month) },
class_name: 'MonthlyRecord'
Controller:
#customers = Customer.
select('customers.id,customers.name,monthly_records.grand_total,stores.name').
includes(:store, :this_month_monthly_records).
references(:stores, :monthly_records)
On view:
- #customers.each do |customer|
- records = customer.this_month_monthly_records
= customer.id
= customer.name
= customer.store.name
= records.average(:grand_total)
= records.sum(:grand_total)
The problem with this way is your_month variable. It's passed in params but I see no safe way to pass it to the model.

Ambiguous column name in Ruby on Rails with SQLite database?

I am getting this error in my Rails app:
ActiveRecord::StatementInvalid in PaymentsController#index
SQLite3::SQLException: ambiguous column name: date: SELECT COUNT(*) FROM "payments" INNER JOIN "invoices" ON "payments"."invoice_id" = "invoices"."id" WHERE "invoices"."user_id" = 1 AND (date >= '2013-01-01' and date <= '2013-12-31')
The problem seems to be that I have a date field in my invoices as well as my payments table.
Yet I still don't know how to fix this error.
class User < ActiveRecord::Base
def number_of_payments_in(year)
payments.where("payments.date >= ? and payments.date <= ?", "#{year}-01-01", "#{year}-12-31").count
end
end
class Payment < ActiveRecord::Base
def self.search(year)
if year
where("date >= ? and date <= ?", "#{year}-01-01", "#{year}-12-31")
end
end
end
Can anybody help?
This answer may be a bit vague as it's not clear from your question which class the self.search(year) method is in, but let me know if this doesn't help and we can try and go further.
My guess is that, unlike in the number_of_payments_in method, in the self.search method you haven't specified an appropriate table in the where call.
In number_of_payments_in, you specify payments.date, but in self.search you just use date. You said that you have a date field in your invoices as well as your payments table, so a join call across both tables will need every reference to date to be scoped by table.
Adding the appropriate table in front of date in self.search (as you have done in number_of_payments_in) may solve the problem.

activerecord comparing times

i am trying to do a query that will be compare the time stored in the database to the current time, and if it is greater than today to display those records.
below is query i am currently using that isnt displaying any records
#schedules = Schedule.where(:team_id => current_user[:team_id], :event => '1', :time => ">= Time.now.zone")
how do i go back query against a timestamp? so that these records will be displayed?
have also tried the following
#schedules = Schedule.find_all_by_team_id_and_event_and_time(current_user[:team_id],"1", :time)
#schedules = Schedule.where("team_id = ? and event = ? and time >= ?", [current_user[:team_id], "1", Time.zone.now])
The string is used directly in the SQL query so you need to make sure the column names are correct and unambiguous (if you joined on another table that also has a team_id colum, you would need to do schedules.team_id = ? and ...)

Find and display nearest date in RoR

I am new to ruby on rails and I'm not sure where to start with this. I have a model for users, and one for projects. Users have many projects, and projects have one user. There is an end_date column in the projects table (as well as a name column).
What I want to do is find the project with the nearest end_date and display it's name and end date on the user's show page.
I tried putting this code in the projects controller, but I do not know if it is working, because I don't know how to access it and display the project name in the view.
def next_deadline(after = DateTime.now, limit = 1)
find(:all, :conditions => ['end_date > ?', after], :limit => limit)
end
Any help would be appreciated. Let me know if more information is needed.
As #Dan mentioned, you do need the :order clause to get the first one, but you should add it to your query and not replace the :conditions (otherwise you'll get the project with the earliest end_date irrespective of your after argument). The way you're defining this method is a bit off though. It should be defined in your Project model (and definitely not the controller) as a class method, or, what I think is a better approach, as a scope. In Rails < 3 (which it seems that you're using):
class Project < ActiveRecord::Base
named_scope :next_deadline, Proc.new { |after = DateTime.now, limit = 1| {:conditions => ['end_date > ?', after], :order => "end_date ASC", :limit => limit} }
...
end
Or in Rails >= 3:
class Project < ActiveRecord::Base
scope :next_deadline, Proc.new { |after = DateTime.now, limit = 1| where('end_date > ?', after).order("end_date ASC").limit(limit) }
...
end
Also, you can always test this kind of code using the Rails console: script/console in Rails < 3, rails c in Rails >= 3.
#projects = Project.find_by_sql("SELECT projects.* FROM projects
JOIN users ON users.id = projects.user_id AND projects.user_id = " + #user.id.to_s + "
WHERE projects.end_date > now()
ORDER BY projects.end_date ASC
LIMIT " + limit)
or
#projects = Project.where(:user_id => #user.id)
.where("end_date > ?", DateTime.now)
.order("end_date ASC")
You want to use :order, not :conditions.
Model.find(:all , :order => "end_date ASC")
Then the first result will be the item with the closest end_date
As Dan said, the condition you wrote won't get the nearest end date, but the dates that are greater than today, or the date passed in as a parameter.
In your User model you could write
def next_deadline_project
self.projects.first
end
as long as you give projects a default scope that orders records by end_date
In order to show information on the view you must set it in an instance variable in the User's controller show method. Instance variables are passed to views and you can access them to display the data.
#project = next_deadline_project
And in your show.html.erb you can use something like:
<%= #project.name %> - <%= #project.end_date %>

Resources