Rails routes with dates - ruby-on-rails-3

So I have a weekly calendar view and I have a route set up to accept /:year/:month/:day for the start date.
match "events/(:year/:month/:day)" => "events#index",
:constraints => { :year => /\d{4}/, :month => /\d{2}/, :day => /\d{2}/ },
:as => "events_date"
I have two questions regarding the use of this route. First, when parsing the params, this is what I'm doing:
unless params[:year].nil? || params[:month].nil? || params[:day].nil?
start_date = Date.new(params[:year].to_i, params[:month].to_i, params[:day].to_i)
end
start_date = start_date.nil? ? Date.today : start_date
This strikes me as pretty verbose and kind of ugly. Is there a better way?
And when making a link to another week in the calendar (for paging week to week), do I have to do something like
#assume an date object with the desired start date
link_to events_date_path(date.strftime('%Y'), date.strftime('%m'), date.strftime('%d'))
Which also seems kind of verbose and ugly. What's the best way to work with dates in routes?

My suggestion would be to not use three separate variables. That way you don't end up with a lot of extra null checking and sanity checking in your controller. You could turn your match in to something look like this, with your constraints still in tact:
match "events/(:date)" => "events#index",
:constraints => { :date => /\d{4}-\d{2}-\d{2}/ },
:as => "events_date"
Thus you would end up with something a little more sane in the controller:
unless params[:date]
start_date = params[:date].strftime("%Y-%m-%d').to_date # assuming you want a Date
end
And I usually do those types of 'if this is set' checks something more like this, because I find it a bit more readable:
start_date = Date.today unless defined? start_date
You could even roll those last two together:
start_date = defined?(params[:date]) ? params[:date].strftime("%Y-%m-%d').to_date : Date.today

Related

RoR Search conditions comparing two columns

What I basically want to do is the following:
a = Assignment.all(:conditions => { :end_date < :start_date })
I only want to select those records on which the end_date is before the start_date.
I actually don't want ending up writing a
for each, push to array if end_date is earlier than start_date.
How can I achieve this in a pretty 'Railsy'-way?
Thank you in advance.
Edit:
I think the problem is comparing the values of both columns. (Allmost) every query is comparing a cell-value to an input-value.
This is a shot in the dark, but maybe one in the right direction ?
Haven't figured out a solution.
It's been a while here but nevertheless, you can just use the ArelTable method:
t = Assignment.arel_table
Assignment.where(t[:end_date].lt(t[:start_date]))
The condition predicates documentation: http://www.rubydoc.info/github/rails/arel/Arel/Predications
The ArelTable documentation: http://www.rubydoc.info/github/rails/arel/Arel/Table
And a good guide: http://jpospisil.com/2014/06/16/the-definitive-guide-to-arel-the-sql-manager-for-ruby.html
a = Assignment.all(:conditions => ["end_date < ?", :start_date ])
Check this: http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-all
I am assuming that you are using ActiveRecord
try
a = Assignment.where('regioassignments.end_date < regioassignments.start_date')
use the tablename followed by the EXACT COLUMNNAMES in the database, since ActiveRecord recognizes this and uses this as SQL directly.
That means the columnname for end_date is probably assignment_expected_end_date from what I figured from one of your comments.
adapted from this answer

rails converting an include query that returns nil into scope lambda

The following query is returning nil in some instances
scope :claim_one, where(" location_id IS NULL OR start_time IS NULL OR archived IS NULL " ).includes(:instructor_assignments).where('instructor_assignments.user_id IS NULL')
I would like to convert the query into a lambda function that takes care of the nil returned by the query as follows ;
scope :claim, (lambda do |claim| where(" location_id IS NULL OR start_time IS NULL OR archived IS NULL ").includes(:instructor_assignments).where('instructor_assignments.user_id IS NULL', claim ) unless claim.nil? end )
The latter does not work as I don't think it has the correct rails syntax
Thank you
Not sure if I fully understand (see comment above), but I hope this will help. I think that the results from your code will be an ActiveRecord::Relation with no records in it rather than nil. I am assuming "claim" is a parameter you want to pass in. If that is the case, you can add it as below.
The preferred way to deal with lambda scopes is much nicer now; just use a class method:
def self.claim_one(claim)
return [whatever you want] unless claim
where(" location_id IS NULL OR start_time IS NULL OR archived IS NULL " ).
includes(:instructor_assignments).
where('instructor_assignments.user_id IS NULL')
end
I would suggest the following though to make your scopes easier to use separately, easier to understand and test, and just darn purty:
def self.incomlete()
where(" location_id IS NULL OR start_time IS NULL OR archived IS NULL " )
end
def self.without_instructor()
includes(:instructor_assignments).where('instructor_assignments.user_id IS NULL')
end
To call this, I would use something like:
result = YourModel.incomplete.without_instructor
if result.empty?
# do yo funky "ain't got no records dance"
else
# record jackpot!
end
Did that answer your question?
Very well, I should have stated things in a much better way
I am using the CanCan gem from Ryan Bates CanCan gem
In my view I have the following code :
<% if can? :claim, #workshop %>
<%= link_to claim_workshop_path(#workshop), :method => :post , :class => "mybtn btn-mini claim-workshop-button" do %>
<%= t(:Claim) %>
<%= content_tag(:i, "", :class => "icon-thumbs-up").html_safe %>
<% end %>
<% end %>
I would like to be able to use te :claim ability from Ryan Bates CanCan
For that I need a scope to be able to use that query, as described in the link above. But sometimes the query return no results -- or nil --.
In my ability.rb file I have the following code that uses the scope
f user.role == "admin" || user.role = "scheduler"
can :manage, :all
can :claim , Workshop.claim do |workshop_instance|
# workshop_instance.can_claim?
workshop_instance.instructor_assignments.nil?
end
else
can :read, :all
end
In the class User I defined the scope need it to obtain my result
scope :claim, where(" location_id IS NOT NULL OR start_time IS NOT NULL " ).includes(:instructor_assignments).where('instructor_assignments.user_id IS NOT NULL')

Query with multiple condition in mongoid

I have some problem with this mongoid. It's my first time to use mongoDB, Before, I always use mySQL.
Here is my problem.
I have model "User". In model "User" has embedded one "Profile",
and I want to search users data with criteria name "dummy" for field "profile.first_name",
"profile.last_name", and "username".
I already use this syntax, but I got empty result:
#filter = "dummy"
#users = User.any_of({'profile.first_name' => /#{#filter}/i, 'profile.last_name' => /#{#filter}/i, :username => /#{#filter}/i})
Try this
#filter = "dummy"
#users = User.any_of({:profile.first_name => "/#filter/i"},{:profile.last_name="/#filter/i"}, {:username => "/#filter/i"})
look at the brackets.

Having a problem with my Model query

Pls i have the following code in my model
Letter.count(:id, :conditions => ["language_id = #{lang} AND :created_at => '#{start_date.to_date.strftime('%Y-%m-%d')}'..'#{end_date.to_date.strftime('%Y-%m-%d')}' " ])
I am trying to get the count of letters.id of different letters between the given dates.
This is the error an having...
Please those anyone know what am doing wrong...Thanks
SQLite3::SQLException: near ">": syntax error: SELECT COUNT("letters"."id") FROM "letters" WHERE ("letters".language_id = 1) AND (language_id = 1 AND :created_at => '2011-05-01'..'2011-05-08
This can be much simplified. A couple points:
You don't use the :created_at => ... format within a string
You need to use between ? and ? for dates.
You don't need to manually strftime your dates, Rails will handle this automatically.
In Rails 3, the preferred way is to use where(...) instead of a :conditions Hash for your count(...).
You should probably use Rails' safe interpolation for your language_id field too
Letter.where("language_id = ? AND created_at between ? and ?", lang, start_date.to_date, end_date.to_date).count

Refactoring SQL

I must connect from my Rails app to a remote database on a Java application.
I have a query like this:
find_by_sql("select c_templateid, c_templateinfoid, c_startdate, c_enddate, c_active,
campaign, shortcode, prefix, c_descriptivename, c_description, c_templatename
from (active_services aser join activity a on aser.c_primaryprefixid =
a.c_primaryprefixid ) join matrix_templateinfo using(c_templateinfoid)
where campaign is not null)")
I need to refactor it to the AR#find() method, because I want later add complex :conditions on it. I dont want convert them into string to append then later to the find_by_sql method.
find(:all,
:select => "c_templateid, c_templateinfoid, c_startdate, c_enddate, c_active,
campaign, shortcode, prefix, c_descriptivename, c_description, c_templatename",
# :joins => WHAT I SHOULD DO HERE ?
:conditions => "campaign is not null"
)
You can also specify complex joins in :joins
:joins => "matrix_templateinfo ON <conditions go here> AND campaing IS NOT NULL"
but you should really start padronizing your field names if you're using rails :]