برنامه نویسی

استراتژی های انتقال داده در Ruby on Rails: راه درست برای مدیریت داده های از دست رفته

بررسی اجمالی

در این مقاله، ما قصد داریم در مورد استراتژی‌های ممکن برای مهاجرت، تولید و پر کردن داده‌ها در برنامه Rails بحث کنیم. ما آنها را پیاده سازی می کنیم، آنها را بهبود می بخشیم، مزایا و معایب آنها را در نظر می گیریم و بحث می کنیم که کدام یک بهتر است در سناریوهای مختلف استفاده شود. تا پایان مقاله، تصویر کاملی از روش های مختلف حل مشکلات انتقال داده خواهیم داشت.

معرفی

به عبارت ساده تر، انتقال داده فرآیند افزودن، به روز رسانی یا انتقال برخی از داده ها در داخل برنامه شما است. محبوب ترین موارد برای انتقال داده ها به شرح زیر است:

  • پر کردن داده های ستون
  • انتقال داده های ستون از یک جدول به جدول دیگر
  • ایجاد رکوردهای جدید پایگاه داده
  • به روز رسانی داده های خراب یا نامعتبر با مقادیر صحیح
  • حذف داده های استفاده نشده

ما 3 روش مختلف را برای انجام آن در نظر خواهیم گرفت:

  • دستکاری مستقیم داده ها
  • Rake Task
  • جواهر مهاجرت داده

دستکاری مستقیم داده ها

اولین گزینه ساده ترین گزینه است: ما فقط داده های از دست رفته را از طریق اضافه می کنیم rails c یا از طریق اتصال مستقیم پایگاه داده در حال تولید.

مزایای:

  • آسان
  • نیازی به پیاده سازی چیز جدیدی نیست
  • سریع است زیرا انتقال داده ها را می توان در چند دقیقه انجام داد.

چالش ها و مسائل:

  • خیلی خطرناک تغییرات ممکن است آنطور که در نظر گرفته شده به پایان نرسد
  • مشکلات دسترسی و امنیتی احتمالی
  • هیچ تست و بررسی کدی وجود ندارد، بنابراین نمی توانیم از کیفیت آن مطمئن باشیم
  • عدم کنترل؛ شما نمی دانید چه کسی مهاجرت را اجرا کرد یا چرا آنها آن را اجرا کردند.

Rake Task

گزینه دوم وظیفه رنک است. در این فصل، ما سعی خواهیم کرد نحوه اضافه کردن صحیح وظایف Rake را درک کنیم، اطمینان حاصل کنیم که آنها به درستی کار می کنند، مزایا و معایب آنها را یاد می گیریم و چگونگی استفاده از آنها برای انتقال داده را بررسی خواهیم کرد. ما با اضافه کردن ساده‌ترین کار رنک شروع می‌کنیم و سپس ساختار آن را بهبود می‌دهیم، منطق را با تست‌ها پوشش می‌دهیم و استفاده از بهترین شیوه‌ها را برای نوشتن انتقال داده‌ها با استفاده از وظایف Rake در نظر می‌گیریم.

بیایید تصور کنیم که یک مدل Animal با فیلدهای زیر داریم:

  • id
  • kind
  • status
  • created_at
  • updated_at

و باید مقدار وضعیت را از آن تغییر دهیم nil به reserved برای همه حیواناتی که قبلاً امروز خلق کردیم. چگونه میتوانیم آنرا انجام دهیم؟ بیایید با اضافه کردن یک الگوی کار ساده Rake شروع کنیم.

# frozen_string_literal: true

# lib/tasks/animals/backfill_statuses.rake

namespace :animals do
  desc "Update animal status to 'reserved' for animals created before today"
  task backfill_statuses: [:environment] do
    puts 'Updating animal status...'
  end
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و بررسی کنید که کار می کند:

rake animals:backfill_statuses
# => Updating animal status...
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

وظیفه اجرا شده است و همانطور که انتظار می رود کار می کند. حالا بیایید کد واقعی را با به روز رسانی پایگاه داده اضافه کنیم. به شکل زیر خواهد بود:

# frozen_string_literal: true

# lib/tasks/animals/backfill_statuses.rake

namespace :animals do
  desc "Update animal status to 'reserved' for animals created before today"
  task backfill_statuses: [:environment] do
    Animal.where(status: nil).where('created_at < ?', Time.zone.today).update_all(status: 'reserved')
  end
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

حالا بیایید بررسی کنیم که آیا کار می کند یا خیر:

rake animals:backfill_statuses
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

وظیفه Rake اجرا شده است و مقادیر پایگاه داده بر این اساس به روز می شوند. خودشه. سناریوی اصلی ما همانطور که انتظار می‌رود کار می‌کند، اما هنوز جا برای بهبود وجود دارد. بیایید نگاهی بیندازیم به آنچه که می توانیم انجام دهیم تا کارمان قابل اعتمادتر شود.

بهبودها

5 زمینه وجود دارد که به طور بالقوه می توانیم آنها را بهبود بخشیم:

  • نمایش نتایج در کنسول برای مشاهده
  • از سازگاری داده ها با تراکنش ها اطمینان حاصل کنید
  • بهینه سازی درخواست های DB
  • کد وظیفه Rake را جدا کنید
  • اضافه کردن تست ها

نمایش نتایج در کنسول برای مشاهده

همانطور که ممکن است متوجه شده باشید، وظیفه Rake در بالا هیچ خروجی را نشان نداده است. این می تواند یک مشکل واقعی باشد زیرا شما نمی دانید که آیا با موفقیت اجرا شده است یا نه، و زمان زیادی را صرف تلاش برای بررسی آن توسط خودتان روی داده های تولید خواهید کرد. بیایید این مشکل را برطرف کنیم:

# frozen_string_literal: true

# lib/tasks/animals/backfill_statuses.rake

namespace :animals do
  desc "Update animal status to 'reserved' for animals created before today"
  task backfill_statuses: [:environment] do
    puts "Before running the rake task, there were #{Animal.where(status: 'reserved').count} animals in the 'reserved' state."

    Animal.where(status: nil).where('created_at < ?', Time.zone.today).update_all(status: 'reserved')

    puts "After running the rake task, there are now #{Animal.where(status: 'reserved').count} animals in the 'reserved' state."
  end
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

حال، بیایید وظیفه رنک را اجرا کنیم:

rake animals:backfill_statuses

# => Before running the rake task, there were 0 animals in the 'reserved' state.
# => After running the rake task, there are now 101 animals in the 'reserved' state.
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

با کد به روز شده، ما تعداد حیوانات را در حالت «رزرو شده» هم قبل و هم بعد از اجرای کار رنک نمایش می دهیم و دید بهتری را ارائه می دهیم و از اجرای موفقیت آمیز کار اطمینان می دهیم.

از سازگاری داده ها با تراکنش ها اطمینان حاصل کنید

اگر برخی از خطاهای غیرمنتظره در وسط انتقال داده ظاهر شوند، چه اتفاقی می‌افتد؟ در حال حاضر، ما آن را اداره نمی کنیم. حتی اگر برای مثالی که ارائه کرده‌ایم حیاتی نباشد، به طور کلی، نباید فراموش کنیم که چنین دستکاری داده‌ها را در یک تراکنش بپیچانیم تا وضعیت داده ثابتی را حفظ کنیم.

# frozen_string_literal: true

# lib/tasks/animals/backfill_statuses.rake

namespace :animals do
  desc "Update animal status to 'reserved' for animals created before today"
  task backfill_statuses: [:environment] do
    ActiveRecord::Base.transaction do
      Animal.where(status: nil).where('created_at < ?', Time.zone.today).update_all(status: 'reserved')
    end
  end
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

با اضافه کردن ActiveRecord::Base.transaction ما اطمینان حاصل می کنیم که تمام به روز رسانی ها به صورت یک عملیات اتمی اجرا می شوند. اگر در حین انتقال داده ها خطایی رخ دهد، تراکنش برگردانده می شود و داده ها بدون تغییر باقی می مانند و یکپارچگی و یکپارچگی داده ها را حفظ می کنند.

بهینه سازی درخواست های DB

ما قبلاً این مشکل را در وظیفه رنک خود حل کرده ایم، اما ذکر این نکته مهم است که در صورت امکان باید از راه حل بهینه پایگاه داده استفاده کنیم. به عنوان مثال، شخصی می تواند وظیفه ما را اینگونه بنویسد:

# frozen_string_literal: true

# lib/tasks/animals/backfill_statuses.rake

namespace :animals do
  desc "Update animal status to 'reserved' for animals created before today"
  task backfill_statuses: [:environment] do
    Animal.where(status: nil).where('created_at < ?', Time.zone.today).each do |animal|
      animal.update(status: 'reserved')
    end
  end
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کد زیر یک درخواست به‌روزرسانی SQL را برای هر حیوانی از لیست آغاز می‌کند و آن را غیربهینه می‌کند:

D, [2023-07-21T09:50:58.346040 #67787] DEBUG -- :   Animal Load (1.6ms)  SELECT `animals`.* FROM `animals` WHERE `animals`.`status` IS NULL AND (created_at < '2023-07-21')
D, [2023-07-21T09:50:58.346735 #67787] DEBUG -- :   ↳ lib/tasks/animals/backfill_statuses.rake:10:in `block (2 levels) in <main>'
D, [2023-07-21T09:50:58.371908 #67787] DEBUG -- :   TRANSACTION (2.2ms)  BEGIN
D, [2023-07-21T09:50:58.372737 #67787] DEBUG -- :   ↳ lib/tasks/animals/backfill_statuses.rake:11:in `block (3 levels) in <main>'
D, [2023-07-21T09:50:58.375091 #67787] DEBUG -- :   Animal Update (2.2ms)  UPDATE `animals` SET `animals`.`status` = 'reserved', `animals`.`updated_at` = '2023-07-21 07:50:58.368697' WHERE `animals`.`id` = 1
D, [2023-07-21T09:50:58.375713 #67787] DEBUG -- :   ↳ lib/tasks/animals/backfill_statuses.rake:11:in `block (3 levels) in <main>'
D, [2023-07-21T09:50:58.381169 #67787] DEBUG -- :   TRANSACTION (5.0ms)  COMMIT
D, [2023-07-21T09:50:58.381524 #67787] DEBUG -- :   ↳ lib/tasks/animals/backfill_statuses.rake:11:in `block (3 levels) in <main>'
D, [2023-07-21T09:50:58.383624 #67787] DEBUG -- :   TRANSACTION (1.3ms)  BEGIN
D, [2023-07-21T09:50:58.384250 #67787] DEBUG -- :   ↳ lib/tasks/animals/backfill_statuses.rake:11:in `block (3 levels) in <main>'
D, [2023-07-21T09:50:58.385792 #67787] DEBUG -- :   Animal Update (1.4ms)  UPDATE `animals` SET `animals`.`status` = 'reserved', `animals`.`updated_at` = '2023-07-21 07:50:58.381901' WHERE `animals`.`id` = 2

...
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

به همین دلیل همیشه منطقی است که سعی کنیم راهی برای انجام آن در یک عملیات DB پیدا کنیم، همانطور که با کد زیر انجام دادیم:

# frozen_string_literal: true

# lib/tasks/animals/backfill_statuses.rake

namespace :animals do
  desc "Update animal status to 'reserved' for animals created before today"
  task backfill_statuses: [:environment] do
    Animal.where(status: nil).where('created_at < ?', Time.zone.today).update_all(status: 'reserved')
  end
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این کد فقط یک درخواست DB را راه اندازی می کند:

Animal Update All (6.8ms)  UPDATE `animals` SET `animals`.`status` = 'reserved' WHERE `animals`.`status` IS NULL AND (created_at < '2023-07-21')
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اگر راهی برای به روز رسانی چیزی در یک درخواست DB وجود ندارد، حداقل باید استفاده از دسته ها را به عنوان یک تمرین خوب در نظر بگیرید:

# frozen_string_literal: true

# lib/tasks/animals/backfill_statuses.rake

namespace :animals do
  desc "Update animal status to 'reserved' for animals created before today"
  task backfill_statuses: [:environment] do
    Animal.where(status: nil).where('created_at < ?', Time.zone.today).find_each do |animal|
      animal.update(status: 'reserved')
    end
  end
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

PS برای دیدن گزارش‌های SQL از وظیفه Rake، می‌توانید کد زیر را داخل آن اضافه کنید:

# frozen_string_literal: true

# lib/tasks/animals/backfill_statuses.rake

namespace :animals do
  desc "Update animal status to 'reserved' for animals created before today"
  task backfill_statuses: [:environment] do
    ActiveRecord::Base.logger = Logger.new(STDOUT)

    # ...
  end
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کد وظیفه Rake را جدا کنید

یکی از مشکلات نه چندان واضحی که ممکن است در هنگام انجام وظایف بسیار زیاد رخ دهد، عدم وجود کپسوله است. بیایید نگاهی به دو کار رنک زیر بیندازیم و سعی کنیم حدس بزنیم چه چیزی می تواند در اینجا اشتباه باشد:

# frozen_string_literal: true

# lib/tasks/animals/task1.rake

namespace :animals do
  task task1: [:environment] do
    puts message
  end

  def message
    'Hello world from Task 1!'
  end
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

# frozen_string_literal: true

# lib/tasks/animals/task2.rake

namespace :animals do
  task task2: [:environment] do
    puts message
  end

  def message
    'Hello world from Task 2!'
  end
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

حالا بیایید هر دوی آنها را اجرا کنیم:

rake animals:task1
# => Hello world from Task 2!
rake animals:task2
# => Hello world from Task 2!
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

آیا توجه کرده اید؟ این چیزی نیست که ما انتظار داشتیم! وظیفه رنک دوم، مقدار متد را از اولی حذف کرد! و این بسیار خطرناک و غیرمنتظره است اگر بخواهید از چیزی مانند این استفاده کنید:

# frozen_string_literal: true

# lib/tasks/animals/task1.rake

namespace :animals do
  task task1: [:environment] do
    query.destroy_all
  end

  def query
    Animal.where(status: nil)
  end
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

  • lib/tasks/animals/task2.rake
# frozen_string_literal: true

# lib/tasks/animals/task2.rake

namespace :animals do
  task task2: [:environment] do
    query.destroy_all
  end

  def query
    Animal.all
  end
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و اجرا:

rake animals:task1
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

شما به جای زیرمجموعه مورد نظر، تمام رکوردهای خود را حذف می کنید!

چگونه می توانیم آن را تعمیر کنیم؟

ما باید وظایف رنک خود را در آن قرار دهیم Rake::DSL کلاس مثل این:

# frozen_string_literal: true

# lib/tasks/animals/task1.rake

module Tasks
  module Animals
    class Task1

      include Rake::DSL

      def initialize
        namespace :animals do
          task task1: [:environment] do
            puts message
          end
        end
      end

      private

      def message
        'Hello world from Task 1!'
      end
    end
  end
end

Tasks::Animals::Task1.new
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

# frozen_string_literal: true

# lib/tasks/animals/task2.rake

module Tasks
  module Animals
    class Task2

      include Rake::DSL

      def initialize
        namespace :animals do
          task task2: [:environment] do
            puts message
          end
        end
      end

      private

      def message
        'Hello world from Task 2!'
      end
    end
  end
end

Tasks::Animals::Task2.new
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و بیایید اجرا کنیم:

rake animals:task1
# => Hello world from Task 1!
rake animals:task2
# => Hello world from Task 2!
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون همه چیز همانطور که انتظار می رود کار می کند. بیایید همان انزوا را برای خودمان اعمال کنیم backfill_statuses وظیفه چنگک زدن

# frozen_string_literal: true

# lib/tasks/animals/backfill_statuses.rake

module Tasks
  module Animals
    class BackfillStatuses

      include Rake::DSL

      def initialize
        namespace :animals do
          desc "Update animal status to 'reserved' for animals created before today"
          task backfill_statuses: [:environment] do
            Animal.where(status: nil).where('created_at < ?', Time.zone.today).update_all(status: 'reserved')
          end
        end
      end

    end
  end
end

Tasks::Animals::BackfillStatuses.new
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

خودشه.

اضافه کردن تست ها

آخرین کاری که برای اطمینان از کیفیت انجام می دهیم اضافه کردن آزمایشات است. بیایید ببینیم چگونه می توانیم وظایف رنک را آزمایش کنیم.

اول از همه، باید کدی را برای بارگذاری وظایف خود تعریف کنیم:

# spec/support/tasks.rb

# frozen_string_literal: true

RSpec.configure do |_config|
  Rails.application.load_tasks
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و آن را در spec/rails_helper.rb:

# spec/rails_helper.rb

require 'support/tasks'
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

سپس تست خود را اضافه می کنیم:

# spec/tasks/animals/backfill_statuses_spec.rb

# frozen_string_literal: true

require 'rails_helper'

RSpec.describe 'rake animals:backfill_statuses', type: :task do
  subject { Rake::Task['animals:backfill_statuses'].execute }

  let(:expected_output) do
    <<~TEXT
      Before running the rake task, there were 1 animals in the 'reserved' state.
      After running the rake task, there are now 2 animals in the 'reserved' state.
    TEXT
  end

  let(:animal_1) { create(:animal, created_at: 10.days.ago, status: nil) }
  let(:animal_2) { create(:animal, created_at: 10.days.ago, status: 'reserved') }
  let(:animal_3) { create(:animal, created_at: 10.days.ago, status: 'another_status') }
  let(:animal_4) { create(:animal, created_at: 10.days.from_now, status: nil) }

  before do
    animal_1
    animal_2
    animal_3
    animal_4
  end

  it "update animal status to 'reserved' for animals created before today" do
    expect { subject }.to change { animal_1.reload.status }.from(nil).to('reserved')
      .and output(expected_output).to_stdout

    expect(animal_2.reload.status).to eq('reserved')
    expect(animal_3.reload.status).to eq('another_status')
    expect(animal_4.reload.status).to be_nil
  end
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

خودشه.

جواهر مهاجرت داده

گزینه سوم استفاده از data-migrate gem است.

بیایید این گوهر را به پروژه خود اضافه کنیم:

# Gemfile

gem 'data_migrate'
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و اجرا کنید:

bundle install
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون می توانید یک انتقال داده ایجاد کنید، همانطور که یک مهاجرت طرحواره ایجاد می کنید:

rails g data_migration backfill_animal_statuses

# => db/data/20230721111716_backfill_animal_statuses.rb
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بیایید مقداری کد به فایل تولید شده اضافه کنیم تا بررسی کنیم که آیا واقعاً کار می کند یا خیر:

# frozen_string_literal: true

class BackfillAnimalStatuses < ActiveRecord::Migration[7.0]
  def up
    puts 'Test Data Migration'
  end

  def down
    # do nothing
  end
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

برای اجرای migration باید از دستور زیر استفاده کنیم:

rake data:migrate
# or
rake db:migrate:with_data
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و خروجی زیر را دریافت می کنیم:

== 20230721111716 BackfillAnimalStatuses: migrating ===========================
Test Data Migration
== 20230721111716 BackfillAnimalStatuses: migrated (0.0000s) ==================
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این مهاجرت فقط یک بار قابل اجرا است. پس بیایید آن را حذف کنیم و یک کد دیگر ایجاد کنیم و کد واقعی را داخل آن اضافه کنیم:

rails g data_migration backfill_animal_statuses

# => db/data/20230721112534_backfill_animal_statuses.rbb
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این چیزی است که پس از افزودن کد منطق کسب و کار خود به دست می آوریم:

# db/data/20230721112534_backfill_animal_statuses.rb

# frozen_string_literal: true

class BackfillAnimalStatuses < ActiveRecord::Migration[7.0]
  def up
    Animal.where(status: nil).where('created_at < ?', Time.zone.today).update_all(status: 'reserved')
  end

  def down
    # do nothing
  end
end
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و بیایید اجرا کنیم:

rake data:migrate
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در اینجا چیزی است که ما دریافت می کنیم:

== Data =======================================================================
== 20230721112534 BackfillAnimalStatuses: migrating ===========================
== 20230721112534 BackfillAnimalStatuses: migrated (0.0221s) ==================
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اساساً، انتقال داده با همان منطق مهاجرت طرح کار می کند، اما به جای ذخیره آخرین نسخه مهاجرت در حال اجرا در schema_migrations جدول، انتقال داده ها نسخه را در جدول دیگری به نام ذخیره می کند data_migrations.

ذکر این نکته مهم است که انتقال داده‌ها در بیشتر موارد باید برگشت‌ناپذیر باشد، اما ما نمی‌خواهیم یک خطای صریح ایجاد کنیم، زیرا از بازگشت به عقب برای تغییرات ساختار طرح جلوگیری می‌کند. در عوض، ما فقط آن را ترک می کنیم down روش خالی به همین دلیل، بهتر است مهاجرت را به صورت غیر توانمند طراحی کنیم تا در صورت امکان چندین بار بتوان آن را اجرا کرد.

انتقال داده هیچ مزیت دیگری به جز مواردی که در بالا به آن اشاره کردیم، ارائه نمی دهد. بنابراین، ما هنوز باید در مورد مشکلاتی که برای وظیفه Rake حل کرده ایم فکر کنیم، مانند نمایش خروجی، اضافه کردن تراکنش ها، بهینه سازی درخواست های DB و غیره.

مقایسه Rake Task و Data Migration Gem

بیایید این دو راه حل را با هم مقایسه کنیم و تصمیم بگیریم که از کدام یک و تحت چه شرایطی استفاده کنیم:

چه زمانی یک کار شن کش بهتر می شود؟

  • زمانی که می خواهید این قابلیت را داشته باشید که زمان و روز دقیقی را که می خواهید اجرا کنید را انتخاب کنید.
  • زمانی که می خواهید این قابلیت را داشته باشید که پلتفرمی را که می خواهید اجرا کنید (مثلاً صحنه سازی یا تولید) را انتخاب کنید.
  • زمانی که می خواهید یک وظیفه Rake را چندین بار اجرا کنید.

چه زمانی گوهر انتقال داده بهتر جا می شود؟

  • وقتی می خواهید مطمئن شوید که داده ها به طور خودکار اضافه می شوند و هیچ کس فراموش نمی کند چیزی را اجرا کند.
  • وقتی ترتیب انتقال طرحواره برای شما مهم است (به عنوان مثال، مهاجرت طرحواره یک ستون جدید اضافه می کند و انتقال داده ها این ستون را پر می کند).
  • زمانی که می خواهید آن را در همه محیط ها بدون تلاش اضافی اجرا کنید.
  • زمانی که باید مهاجرت را فقط یک بار اجرا کنید.

بنابراین، به طور کلی، وظیفه Rake بسیار انعطاف‌پذیرتر و قابل آزمایش‌تر است و می‌تواند وظایف مشابه انتقال داده را پوشش دهد، اما ممکن است به تلاش بیشتری نیاز داشته باشد. انتقال داده‌ها بسیار سخت‌گیرانه‌تر هستند، اما برخی از اتوماسیون‌ها و ترتیب اجرای دقیق را ارائه می‌دهند که با تغییرات طرحواره مرتبط هستند.

به عنوان مثال، اگر شما نیاز به پشتیبانی از ساختار مجدد طرحواره پایگاه داده دارید و نمی خواهید داده ها را در طول این تغییرات از دست بدهید، gem انتقال داده بسیار مناسب است. به عنوان مثال، اگر شما نیاز به تغییر نام یک ستون دارید و می خواهید مقادیر را از ستون قدیمی به ستون جدید کپی کنید، سپس تنظیم کنید NULL=false محدود کردن به جدید، و سپس حذف کامل قدیمی، جواهر مهاجرت داده، این فرآیند را در مقایسه با استفاده از وظیفه رنک بسیار آسان‌تر می‌کند.

از سوی دیگر، اگر کار با تغییرات طرح پایگاه داده ارتباطی نداشته باشد، یک کار رنک ممکن است انتخاب مناسب تری باشد. انعطاف پذیری و آزمایش پذیری بیشتری را ارائه می دهد و مدیریت وظایفی را که مستقیماً با تغییرات طرحواره مرتبط نیستند آسان تر می کند.

نتیجه

در طول این مقاله، ما استراتژی‌های مختلف برای انتقال داده، تولید و پر کردن داده‌ها در یک برنامه Rails را بررسی کرده‌ایم. ما با در نظر گرفتن مزایا و معایب آنها، این استراتژی ها را اجرا و بهبود بخشیده ایم. علاوه بر این، ما دو راه‌حل اصلی، وظیفه rake و gem مهاجرت داده را مقایسه کرده‌ایم و مناسب بودن آنها را در سناریوهای مختلف بررسی کرده‌ایم.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا