Champer Wu
Champer Wu

Reputation: 1271

How can I group by date of range between start time and end time in Ruby On Rails?

I trying to create a calendar list

Migrate:

class CreateCalendars < ActiveRecord::Migration
  def change
    create_table :calendars do |t|
      t.string :title
      t.text :description
      t.datetime :start_time
      t.datetime :end_time

      t.timestamps null: false
    end
  end
end

View:

<% @dates.each do |day, posts| %>
 <%for daytime in day%>
  <h4 class="other_day_title"><%= daytime %></h4>
  <% posts.each do |post| %>
   <p class="post_title">。<%= post.title %></p>
  <%end%>
 <%end%>
<%end%>

Controller:

def index
@posts = Post.all.order(:start_time)
@date = params[:month] ? Date.parse(params[:month]) : Date.today
@dates = @posts.group_by {|t| t.start_time.to_date..t.end_time.to_date}
end

The output is:

enter image description here

Two posts is overlap

How can I display this:

2016-02-09

2016-02-10

2016-02-11

2016-02-12

Upvotes: 0

Views: 1046

Answers (2)

faron
faron

Reputation: 1059

I think group is not quite what you want to achieve. What about doing it this way:

@dates =  @posts.each_with_object({}) do |post, acc|
  (post.start_date..post.end_date).each do |date|
    (acc[date] ||= []) << post
  end
end

Upvotes: 0

Michael Cruz
Michael Cruz

Reputation: 882

In your controller:

@dates = @posts.map { |post| (post.start_time.to_date..post.end_time.to_date).to_a }.flatten.uniq

Then, in your view:

<% @dates.each do |day| %>
  <h4 class="other_day_title"><%= day %></h4>
  <% @posts.select { |post| ((post.start_time.to_date..post.end_time.to_date).to_a).include? day }.each do |post| %>
    <p class="post_title">。<%= post.title %></p>
  <%end%>
<%end%>

Since @dates now only has the dates, you iterate through those. Then for each of those, you select each post where that day is in the range of its start_time.to_date..end_time.to_date, so that it will list each post that was happening on that date.

Edit @dates now includes every date that is in any range of start_time.to_date..end_time.to_date for any given object. It then flattens the array and selects only the unique elements, iterating over those in the view.

Upvotes: 1

Related Questions