Jason Mark Beaton
Jason Mark Beaton

Reputation: 27

Creating 30 empty records on create

I'm working on a fitness tracking app where we encourage you to track a habit for 30 days.

Every user has_many projects, projects belong_to user, projects has_many tasks, and tasks belong_to projects.

What I'm looking to do is when a project is created, I want to populate 30 empty tasks which will be displayed in order of day, and allow the user to click on a day and update the task. (see image) enter image description here

I'm happy to post any of the code/views if you need reference. Thanks for the help!

Upvotes: 0

Views: 39

Answers (2)

max
max

Reputation: 102443

class Project < ActiveRecord::Base
  has_many :tasks

  def create_tasks!(n = 30)
    self.class.transaction do
      1..n.each do |day|
        self.tasks.create(day: day)
      end 
    end
  end
end

Wrapping a mass insert in a single transaction is vital for performance - otherwise each insert will be run in its own transaction.

You could use a after_create model callback to call create_tasks! - but this can be problematic since the callback will fire every time you create a project which can make tests slow.

class Project < ActiveRecord::Base
  has_many :tasks
  after_create :create_tasks!

  def create_tasks!(n = 30)
    self.class.transaction do
      1..n.each do |day|
        self.tasks.create(day: day)
      end 
    end
  end
end

Another way to this would be to call it in your controller:

class ProjectsController < ApplicationController
  def create
    @project = Project.new(project_params)
    if @project.save
      @project.create_tasks!
      redirect_to @project
    else
      render :new
    end
  end 
end

Which gives you better control over exactly where in the application it happens.

Upvotes: 1

alecananian
alecananian

Reputation: 1152

You can make use of Active Record's after_create callback, which allows you to perform a task whenever a new record is created for a certain model:

class Project < ActiveRecord::Base
    has_many :tasks

    after_create :create_empty_tasks

    private
        def create_empty_tasks
            # Create your 30 Task objects
            30.times do |i|
                Task.create(day: (i + 1), project: self) # Update to match your schema
            end
        end
end

You'll of course need to update that code to pass any user-specific data into the Task, but hopefully the callback is a good starting point.

Upvotes: 1

Related Questions