Rails Execution

Rails Execution is an Engine to manage the Rails scripts for migration, cleanup, and fixing the bad data without deployment.

  • Supported the Syntax checker
  • Supported the Execution logs
  • Supported the Reviewing process
  • Supported the Attachment files
  • Supported the Comments communication
  • Supported the Activities tracking

image image

Installation

Add the following line to your Gemfile:

gem 'rails_execution'

Then run bundle install

Getting started

How to setup

You need to run the generator:

    $ rails g rails_execution:install

And you can change the config in config/initializers/rails_execution.rb

Default is Solo Mode, without the Reviewing process.

Enable the Reviewing process

The first step is to disable the Solo Mode

    config.solo_mode = false

And then uncomment the configures of the owner and reviewers

    config.owner_model = 'User'
    config.owner_method = :current_user
    config.owner_name_method = :name
    config.owner_avatar = ->(owner) { owner.avatar.url }

    config.reviewers = -> do
      User.where(is_admin: true).map do |user|
        {
          name: user.name,
          id: user.id,
          type: 'User',
          avatar_url: user.avatar.url,
        }
      end
    end

Enable the Attachment files

Run the generator to add the FileUploader and FileReader

    $ rails g rails_execution:file_upload

And then uncomment the file upload

  config.file_upload = true
  config.file_uploader = ::RailsExecution::FileUploader
  config.file_reader = ::RailsExecution::FileReader

To limit the File types. Default: .png, .gif, .jpg, .jpeg, .pdf, .csv You can modify the limitation like this

  config.acceptable_file_types = {
    '.jpeg': 'image/jpeg',
    '.pdf': 'application/pdf',
    '.csv': ['text/csv', 'text/plain'],
  }

Control the Permissions

For example with Pundit authorization.

  config.task_creatable = lambda do |user|
    YourPolicy.new(user).creatable?
  end
  config.task_editable = lambda do |task, user|
    YourPolicy.new(user, task).editable?
  end
  config.task_closable = lambda do |task, user|
    YourPolicy.new(user, task).closable?
  end
  config.task_approvable = lambda do |task, user|
    YourPolicy.new(user, task).approvable?
  end
  config.task_executable = lambda do |task, user|
    YourPolicy.new(user, task).executable?
  end

Setup the Logger

To storage the logfile

  config.logging = lambda do |file, task|
    LoggerModel.create!(task: task, file: file)
  end

And list the logfiles on Task page

  config.logging_files = lambda do |task|
    LoggerModel.where(task: task).map do |log|
      log.file.expiring_url(30.minutes.to_i)
    end
  end

In case you want to render logs more fancy in the view, you need to return list of file and created_at

  config.logging_files = lambda do |task|
    LoggerModel.where(task: task).map do |log|
      [log.file.expiring_url(30.minutes.to_i), log.created_at]
    end
  end

Enable Task Schedule

Depend on which gem you use to schedule a job you need to modify the block inside lambda function to invoke ::RailsExecution::Services::TaskScheduler.call(task_id)

In this case Sidekiq is used with option delay_until and set to run at scheduled_at

  config.task_schedulable = true
  config.task_scheduler = ->(scheduled_at, task_id) { ::RailsExecution::Services::TaskScheduler.delay_until(scheduled_at).call(task_id) }
  config.scheduled_task_remover = ->(task_id) { Sidekiq::ScheduledSet.new.find_job(jid).delete }

Enable Task Background

Depend on which gem you use to run background job you need to modify the block inside lambda function to invoke ::RailsExecution::Services::BackgroundExecution.call(task_id)

  config.task_background = true
  config.task_background_executor = ->(task_id) { ::RailsExecution::Services::BackgroundExecution.delay.call(task_id) }

Others

To change the Per page of the tasks list. Default value: 20

  config.per_page = 10

Pro-tips

Logging
  • In editor, you can call the log method with message to log the message to logfile

Example:

  log('Read upload file successful')

Output:

  ==================== Wed, 22 Mar 2023 00:31:48
  Read upload file successful

And within the label liked it

  log('Success', 'Read upload file')

Output:

  ==================== Success
  Read upload file
Show object Information
  • If you want to show the object information in loop or in the step by step, you can use the info method to show Model name and id. ruby ids = [1, 2] Product.where(id: ids).each do |product| info(product) # Your code to process the product end

Output:

  ==================== Product#1
  ==================== Product#2
Force to stop the process

If you want to add the message to log and STOP process, you can use the error! method

Example:

  error!('Bad-data', 'Unmatched value!') if var_x != var_y

Output:

  ==================== Bad-data
  Unmatched value!
  ==================== Rolling back...

OR you can use the stop! method to Stop the process

Example:

stop!

or

stop!('bad-data')