0

I'm trying to calculate and display a date using a virtual attribute in Rails. I have a model, Group, and each Group has several GroupMeetings. There is also a GroupDates table that stores the first start date of each Group (submitted via a form by the admin) as well as time zone. Groups meet for a number of weeks determined by the admin.

Because the GroupDates table already exists, I want to calculate each meeting date using the start date and number of weeks without saving the date in the GroupMeetings table. I'm trying to use a virtual attribute to save the meeting date and display it, but it's obviously not persisting. Is there a way to do this without saving the meeting dates in a column on GroupMeeting?

In my model, I select all of the GroupMeetings for a group (which are created when an admin marks a group as active) and try to iterate through, giving the first meeting the same date as the group start date and each subsequent meeting + 7.days after the previous meeting. In a view, I iterate through each GroupMeeting to display fields in an edit form so moderators can update the meeting topics and notes. I want to display the meeting date above each topic field.

GroupMeeting Model:

class GroupMeeting < ActiveRecord::Base
  belongs_to :group
  has_many :users, through: :group, as: :group_users

  validates :group, presence: true

  attr_accessor :meeting_date

  def generate_meeting_date
    @meetings = GroupMeeting.where(group_id: self.group_id).order('id ASC')

    @meetings.each_with_index do |meeting, index|
      if self == @meetings.first
        self.meeting_date = self.group.start_date
      else
        previous = @meetings[index-1]
        self.meeting_date = previous.meeting_date + 7.days
      end
    end

     return self.meeting_date.strftime("%a %b%e, %Y at %k%p")
  end

end

Relevant View/Edit Form:

<% @group_meetings.each do |meeting| %>
 <%= fields_for 'meetings[]', meeting do |m| %>
  <div class="field">
    <strong><%= meeting.generate_meeting_date %></strong>
    <%= m.text_field :topic, label: false %>
  </div>
  <div class="field">
    <%= m.text_field :notes, label: false %>
 </div>
<% end %>
ev662
  • 69
  • 1
  • 10

1 Answers1

1

I think you're on the right track, just missing an attribute. You can create a virtual attribute for your instance method also, and that should fix it.

class GroupMeeting < ActiveRecord::Base
  belongs_to :group
  has_many :users, through: :group, as: :group_users

  validates :group, presence: true

  attr_accessor :meeting_date, :generate_meeting_date

  def generate_meeting_date
    @meetings = GroupMeeting.where(group_id: self.group_id).order('id ASC')

    @meetings.each_with_index do |meeting, index|
      if self == @meetings.first
        self.meeting_date = self.group.start_date
      else
        previous = @meetings[index-1]
        self.meeting_date = previous.meeting_date + 7.days
      end
    end

     return self.meeting_date.strftime("%a %b%e, %Y at %k%p")
  end

end

Although, for displaying a value in the UI, I might look at using a helper instead of an instance method on your class.

ev662
  • 69
  • 1
  • 10
Andrew
  • 375
  • 2
  • 12
  • Good point about the helper method vs class method. Will try with the additional attribute. Thanks! – ev662 Oct 06 '17 at 13:19