This blog is part of our Rails 5 series.
Rails 5 has added some nice enhancements to Active Support. This blog will go over some of those changes.
Improvements in Date, Time and Datetime
prev_day and next_day
As the name of the methods suggests, next_day returns next calendar date.
Similarly, prev_day returns previous calendar date.
1 2Time.current 3=> Fri, 12 Feb 2016 08:53:31 UTC +00:00 4 5Time.current.next_day 6=> Sat, 13 Feb 2016 08:53:31 UTC +00:00 7 8Time.current.prev_day 9=> Thu, 11 Feb 2016 08:53:31 UTC +00:00 10
Support for same_time option to next_week and prev_week
In Rails 4.x next_week returns beginning of next week and prev_week returns beginning of previous week.
In Rails 4.x these two methods also accept week day as a parameter.
1 2Time.current 3=> Fri, 12 Feb 2016 08:53:31 UTC +00:00 4 5Time.current.next_week 6=> Mon, 15 Feb 2016 00:00:00 UTC +00:00 7 8Time.current.next_week(:tuesday) 9=> Tue, 16 Feb 2016 00:00:00 UTC +00:00 10 11Time.current.prev_week(:tuesday) 12=> Tue, 02 Feb 2016 00:00:00 UTC +00:00 13
By using week day as parameter we can get the date one week from now but the returned date is still the beginning of that date. How do we get one week from the current time.
Rails 5 add an additional option same_time: true to solve this problem.
Using this option, we can now get next week date from the current time.
1 2Time.current 3=> Fri, 12 Feb 2016 09:15:10 UTC +00:00 4 5Time.current.next_week 6=> Mon, 15 Feb 2016 00:00:00 UTC +00:00 7 8Time.current.next_week(same_time: true) 9=> Mon, 15 Feb 2016 09:15:20 UTC +00:00 10 11Time.current.prev_week 12=> Mon, 01 Feb 2016 00:00:00 UTC +00:00 13 14Time.current.prev_week(same_time: true) 15=> Mon, 01 Feb 2016 09:16:50 UTC +00:00 16
on_weekend?
This method returns true if the receiving date/time is a Saturday or Sunday.
1 2Time.current 3=> Fri, 12 Feb 2016 09:47:40 UTC +00:00 4 5Time.current.on_weekend? 6=> false 7 8Time.current.tomorrow 9=> Sat, 13 Feb 2016 09:48:47 UTC +00:00 10 11Time.current.tomorrow.on_weekend? 12=> true 13
on_weekday?
This method returns true if the receiving date/time is not a Saturday or Sunday.
1 2Time.current 3=> Fri, 12 Feb 2016 09:47:40 UTC +00:00 4 5Time.current.on_weekday? 6=> true 7 8Time.current.tomorrow 9=> Sat, 13 Feb 2016 09:48:47 UTC +00:00 10 11Time.current.tomorrow.on_weekday? 12=> false 13
next_weekday and prev_weekday
next_weekday returns next day that is not a weekend.
Similarly, prev_weekday returns last day that is not a weekend.
1 2Time.current 3=> Fri, 12 Feb 2016 09:47:40 UTC +00:00 4 5Time.current.next_weekday 6=> Mon, 15 Feb 2016 09:55:14 UTC +00:00 7 8Time.current.prev_weekday 9=> Thu, 11 Feb 2016 09:55:33 UTC +00:00 10
Time.days_in_year
1# Gives number of days in current year, if year is not passed. 2Time.days_in_year 3=> 366 4 5# Gives number of days in specified year, if year is passed. 6Time.days_in_year(2015) 7=> 365 8
Improvements in Enumerable
pluck
pluck method is now added to Enumerable objects.
1 2users = [{id: 1, name: 'Max'}, {id: 2, name: 'Mark'}, {id: 3, name: 'George'}] 3 4users.pluck(:name) 5=> ["Max", "Mark", "George"] 6 7# Takes multiple arguments as well 8users.pluck(:id, :name) 9=> [[1, "Max"], [2, "Mark"], [3, "George"]] 10
one great improvement in ActiveRecord due to this method addition is that when relation is already loaded then instead of firing query with pluck, it uses Enumerable#pluck to get data.
1 2# In Rails 4.x 3users = User.all 4SELECT `users`.* FROM `users` 5 6users.pluck(:id, :name) 7SELECT "users"."id", "users"."name" FROM "users" 8 9=> [[2, "Max"], [3, "Mark"], [4, "George"]] 10 11 12# In Rails 5 13users = User.all 14SELECT "users".* FROM "users" 15 16# does not fire any query 17users.pluck(:id, :name) 18=> [[1, "Max"], [2, "Mark"], [3, "George"]] 19
without
This method returns a copy of enumerable without the elements passed to the method.
1 2vehicles = ['Car', 'Bike', 'Truck', 'Bus'] 3 4vehicles.without("Car", "Bike") 5=> ["Truck", "Bus"] 6 7vehicles = {car: 'Hyundai', bike: 'Honda', bus: 'Mercedes', truck: 'Tata'} 8 9vehicles.without(:bike, :bus) 10=> {:car=>"Hyundai", :truck=>"Tata"} 11
Array#second_to_last and Array#third_to_last
1 2['a', 'b', 'c', 'd', 'e'].second_to_last 3=> "d" 4 5['a', 'b', 'c', 'd', 'e'].third_to_last 6=> "c" 7
PR for these methods can be found here.
Integer#positive? and Integer#negative?
positive? returns true if integer is positive.
negative? returns true if integer is negative.
1 24.positive? 3=> true 4 54.negative? 6=> false 7 8-4.0.positive? 9=> false 10 11-4.0.negative? 12=> true 13
Commit for these methods can be found here.
These changes have now been added to Ruby 2.3 also.
Array#inquiry
Rails team has added ArrayInquirer to ActiveSupport which gives a friendlier way to check its contents.
Array#inquiry is a shortcut for wrapping the receiving array in an ArrayInquirer
1 2users = [:mark, :max, :david] 3 4array_inquirer1 = ActiveSupport::ArrayInquirer.new(users) 5 6# creates ArrayInquirer object which is same as array_inquirer1 above 7array_inquirer2 = users.inquiry 8 9array_inquirer2.class 10=> ActiveSupport::ArrayInquirer 11 12# provides methods like: 13 14array_inquirer2.mark? 15=> true 16 17array_inquirer2.john? 18=> false 19 20array_inquirer2.any?(:john, :mark) 21=> true 22 23array_inquirer2.any?(:mark, :david) 24=> true 25 26array_inquirer2.any?(:john, :louis) 27=> false 28