user1339113
user1339113

Reputation: 65

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.

Upvotes: 1

Views: 3474

Answers (4)

tsherif
tsherif

Reputation: 11710

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.

Upvotes: 4

Eric Sites
Eric Sites

Reputation: 1534

@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")

Upvotes: 1

Christian
Christian

Reputation: 1258

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 %>

Upvotes: 0

Dan
Dan

Reputation: 53

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

Upvotes: 0

Related Questions