S Craig
S Craig

Reputation: 281

Ruby on Rails: Allowing separate Calendars to share the same Event?

I'm having some trouble with the theory (and code) behind my events creator. A quick overview: I have Customers (the users) who each own a Calendar. A Calendar belongs_to a Customer Each Calendar has_many Events, and an Event belongs_to a Calendar:

#customer.rb
class Customer < ActiveRecord::Base
  belongs_to :business
  has_one :calendar, :dependent => :destroy
...
end 

#calendar.rb
class Calendar < ActiveRecord::Base
  belongs_to :customer
  has_many :events, :dependent => :destroy    
end

#event.rb
class Event < ActiveRecord::Base
  belongs_to :calendar

end

When a Customer fills in a form in events\new.html.erb the Events_controller's create action picks up the info from the form, including an array id_array of each participant Customer that the creator of the event wished to be involved.

So far, I have made it so that the events_controller iterates through the array and creates a corresponding Event for each of the participating customer's Calendar:

def create

    @calendar = current_customer.calendar
    @newevent = @calendar.events.build(event_params) #creates event in creator's calendar

    @participant_ids = params[:id_array]

    @participant_ids.each do |item| #iterates through id array, finds corresponding customer and creates event
      @participant = Customer.find(item)
      @part_calendar = @participant.calendar 
      @part_event = @part_calendar.events.build(event_params) #adds event to participant's calendar
    end

    if @newevent.save
      redirect_to '/main' #'/main/#{@calendar.id}'
    else
      redirect_to '/compose'
      end

  end

However, this is clearly not satisfactory, because none of these events created are connected to each other at all. I would like to know what the best most efficient and rubyish way is to allow all these Customer's Calendars to share the event (or share a unique identifier). This is so that if the creator decides to delete the event, it will be deleted from all participating calendars.

Here is also my event db migrate file for reference:

class CreateEvents < ActiveRecord::Migration
  def change
    create_table :events do |t|

      t.timestamps
      t.references :calendar, foreign_key: true

      t.string :name
      t.string :description
      t.date :day
      t.datetime :starts_at
      t.datetime :ends_at
      t.string :location

    end
  end
end

Upvotes: 1

Views: 168

Answers (1)

mtkcs
mtkcs

Reputation: 1716

You can have the Event self referenced: An event will have many events and belongs to an event:

Model

class Event < ActiveRecord::Base
  has_many :events, dependent: :destroy
  belongs_to :event, class_name: "Event"
end

You will have to add event_id to your migration as an integer

Controller

  def create
    @calendar = current_customer.calendar
    @newevent = @calendar.events.build(event_params) #creates event in creator's calendar

    if @newevent.save
      # We wait until it's saved because we need its id
      @participant_ids = params[:id_array]
      @participant_ids.each do |item|
        @participant = Customer.find(item)
        @part_calendar = @participant.calendar 
        # We merge the newly created event id to the params
        @part_event = @part_calendar.events.
          build(event_params.merge(event_id: @newevent.id))
        @part_event.save
      end
      redirect_to '/main' #'/main/#{@calendar.id}'
    else
      redirect_to '/compose'
    end
  end

This way you will have this:

Let's say that customer has a calendar and through your form you created an event and also selected other customers to be part of this event:

The current_customer will have new event, each of the other customers you selected will have a new event ( which have a shared parent event which is the new event of the current_customer). This way:

  • The newly created event will have a children events via event.events as you wiched
  • If you destroy the event of the current_customer, all it's children events will be destroy
  • You can access a parent event of a particular event via event.event

Upvotes: 1

Related Questions