Home > Enterprise >  How to check range between two dates with rails 6
How to check range between two dates with rails 6

Time:08-15

Hello i have this blog module where my posts can have 3 states "no_status" "in_draft" and "published", the user can set the publish_date and publish_end_date for his posts while this range between the dates is fulfilled, the status of the post must be "published", and when it is finished return to "in_draft"

def post
  if self.no_status? || self.in_draft?
    if self.publish_date >=Date.today && self.publish_end <= Date.today
      self.update_attribute :status, 'published'
    end
  elsif self.published?
    if self.publish_date.past? && self.publish_end.past?
      self.update_attribute :status, 'in_draft'
    end
  end
end

What is the proper way to manage this, i have a big problem with my conditions.

CodePudding user response:

You can use Range#cover?. It basically takes a range and checks if the date is withing the start/end;

(10.days.ago..1.day.ago).cover?(3.days.ago)
# true

So, in your case;

(publish_date..publish_end).cover?(Date.today)

CodePudding user response:

In the 1st branch your conditionals are mixed up now, they should be opposite (that's why it doesn't work as expected - you check than publish_date is greater that current date, but this is wrong - it must be in the past to have the post published today). So if you simply "mirror" your conditional operators it should work - but there are cleaner ways of writing the same:

Date.today.between?(publish_date, publish_end)
# or
(publish_date..publish_end).cover?(Date.today)

In the 2nd branch checking that pulish_end date is n the past should be enough. Checking if publish_date is in the past too is redundant - if it is not you have bigger problems what just a wrong status :) - this kind of basic data integrity is better to be addressed by model validations.

Also, the nested ifs are absolutely unnecessary here, they just make the code harder to reason about.

To summarize, something like the following should do the job (I'm not discussing here how this method is being used and whether it should be written this way or not - just addressing the initial question)

def post
  new_status =
    if published? && publish_end.past?
      'in_draft'
    elsif Date.today.between?(publish_date, publish_end)
      'published'
    end
  
  update_attribute :status, new_status
end

CodePudding user response:

You can use Object#in?

def post
  if no_status? || in_draft?
    update(status: 'published') if Date.today.in?(publish_date..publish_end)
  elsif published?
    update(status: 'in_draft') if publish_date.past? && publish_end.past?
  end
end

(BTW you don't need self in Ruby every time)

  • Related