I'm new to rails and am unsure of the best way of doing this. I have a User which "has many" Events. I want to be able to go user.active? in a view which will display whether the user has one or more associated Events created in the last 5 minutes.
I know the syntax isn't correct but this is what I've got so far:
def active?
find(:conditions => {:events => ["created_at >= ?", DateTime.now - 5.minute]}).count > 0
end
You can just do a find on the events collection:
def active?
events.where('created_at >= ?', 5.minutes.ago).count > 0
end
Related
So I want to output users that signed in 2 hours ago with the hope I will call it on the front end, and I have a database attribute (created_at)that keeps track of the time you sign in.
What I did was to define a scope to handle that which got nothing from. Here is my code below:
class SignupHistory < ActiveRecord::Base
scope :one_hour_ago, -> { where 'created_at > ?', Time.now - 2.hours.ago }
end
How do I go about showing users that logged in 2 hours ago?
Am I correct to understand that you are trying to find all the records that were created within the last two hours? Then, you can just test against 2.hours.ago without any subtraction operator:
scope :two_hours_ago, -> { where 'created_at > ?', 2.hours.ago }
I think your problem is that you're calling .ago.
You should be able to accomplish what you need by calling:
scope :one_hour_ago, -> { where 'created_at > ?', Time.zone.now - 2.hours }
I'm having a little trouble with a query in Rails.
Actually my problem is:
I want to select all users which do not have any user_plans AND his role.name is equals to default... OR has user_plans and all user_plans.expire_date are lower than today
user has_many roles
user has_many user_plans
users = User.where(gym_id: current_user.id).order(:id)
#users = []
for u in users
if u.roles.pluck(:name).include?('default')
add = true
for up in u.user_plans
if up.end_date > DateTime.now.to_date
add = false
end
end
if add
#users << u
end
end
end
This code up here, is doing exactly what I need, but with multiple queries.
I don't know how to build this in just one query.
I was wondering if it is possible to do something like
where COUNT(user_plans.expire_date < TODAY) == 0
User.joins(:user_plans, :roles).where("roles.name = 'default' OR user_plans.expire_date < ?", Date.today)
Should work, not tested, but should give you some idea you can play with (calling .distinct at the end may be necessary)
There is also where OR in Rails 5:
User.joins(:user_plans, :roles).where(roles: { name: 'default' }).or(
User.joins(:user_plans).where('user_plans.expire_date < ?', Date.today)
)
FYI: Calling .joins on User will only fetch those users who have at least one user_plan (in other words: will not fetch those who have no plans)
Rails adds and populates a created_at column for new records.
How can I use the to count the number of days that have records within a specified timeframe? (note: counting days, not counting records).
For example, say I have a Post model, how can I calculate how many days in the last year have a Post?
Since you asked for the ruby way, here it is:
Post.where('created_at >= ?', 1.year.ago).map { |p| p.created_at.beginning_of_day }.uniq.size
Update
You can put the following in your Post model
def self.number_of_days
where('created_at >= ?', 1.year.ago).map { |p| p.created_at.beginning_of_day }.uniq.size
end
Then in your controller you can do stuff like
#user.posts.number_of_days
Here's a more efficient way that delegates most of the work to the database (MySQL, not sure if it'll work on others):
Post.where('created_at >= ?', 1.year.ago).group('DATE(created_at)').length
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 %>
So I have my rails application and I have blog posts in my application.
For starters I am on rails 2.3.5 and Ruby 1.8.7
For the show page, I am required to give a prev/next link to the prev/next blog post.
The catch is that I need to find the next blog where the language column in the database is equal to 'eng'. I had started writing this out in my model and it works but of course this will just find the prev/next record in the database no matter what the language is specified in the column and it will break when the record is not found.
def next(lang='eng')
BlogEntry.find(self.id - 1)
end
def prev(lang='eng')
BlogEntry.find(self.id + 1)
end
Try this. This won't break missing records.
BlogEntry.find(:first, :conditions => ["id > ? AND lang = ?", self.id, lang])
and
BlogEntry.find(:first, :conditions => ["id < ? AND lang = ?", self.id, lang])
It's generally dangerous to do id math like this because you can't guarantee that it exists. For instance, suppose you have records with id 1, 2 and 3, then you delete record 3 but create a new record, ActiveRecord will assign that to is 4 (even though 3 is not a record anymore. So if you were to do a find(self.id + 1) on record 2, you will receive an error.
The easiest way to do this is probably with a 'where' statement.
def next(lang='eng')
BlogEntry.where(:lang => lang).where("id > ?", self.id).first
end
and
def prev(lang='eng')
BlogEntry.where(:lang => lang).where("id < ?", self.id).last
end
I'm not familiar with the syntax of Rails version you are using, but it's probably very similar if not the same.