reset_column_information은 코드 냄새입니까?
reset_column_information
메서드를 사용하는 마이그레이션을 작성한 적이 있을 것입니다. 방금 수정한 테이블이나 열 주변의 일부 데이터를 조정하려는 경우에 자주 사용됩니다.사용하는데 어떤 문제가 있나요?
마이그레이션은 데이터베이스 구조 변경에만 관심을 가져야 합니다. 데이터를 추가하거나 제거하기 시작하면 새 개발자가 프로젝트를 설정할 때 실행할 수 없는 시나리오로 이어집니다. 대신 그들은 그들에게 제공된 데이터베이스를 강제로 사용하게 될 것이며, 종종 이것은 프로덕션의 백업이 될 것입니다(큰 데이터 누출 위험이 있음).
무엇을 조심해야 합니까?
bin/setup
라는 모델을 만들고 다음과 같은 일부 데이터를 채운다고 가정해 보겠습니다.class CreateJobLevels < ActiveRecord::Migration[6.0]
def up
create_table :job_levels do |t|
t.string :name
end
JobLevel.reset_column_information
JobLevel.create(name: 'executive')
JobLevel.create(name: 'manager')
end
end
이것의 큰 "아, 아니요"측면은 이제 모든 미래의 개발자가 데이터베이스의
rails db:setup
테이블을 채우기 위해 이 마이그레이션을 실행하도록 요구한다는 것입니다. 개발자가 마이그레이션을 실행하지 않으면 데이터를 추가할 다른 방법을 찾아야 합니다. 또한 JobLevel
필드 주변의 유효성 검사가 변경되면 개발자는 백지 상태에서 실행할 수 없습니다.다음은 매우 일반적이지만 문제가 있는 또 다른 예입니다.
class AddEnabledToJobLevels < ActiveRecord::Migration[6.0]
def up
add_column :job_levels, :enabled, :boolean, default: false, null: false
JobLevel.reset_column_information
JobLevel.update_all(enabled: true)
end
end
두 예에서
job_levels
모델의 이름이 바뀌면 마이그레이션을 다시 실행할 수 없습니다.더 나은 접근 방식은 무엇입니까?
이름을 통한 SQL
JobLevel
메서드를 사용하면 마이그레이션 중에 임의의 SQL을 실행할 수 있습니다. 예:class AddEnabledToJobLevels < ActiveRecord::Migration[6.0]
def up
add_column :job_levels, :enabled, :boolean, default: false, null: false
execute('UPDATE job_levels SET enabled = TRUE')
end
end
앱의 현재 상태가 아닌 마이그레이션 시점에서 데이터베이스의 제약 조건으로 실행되기 때문에 저는 이것을 정말 좋아합니다. 따라서
execute
모델을 삭제하더라도 나중에 이 마이그레이션을 다시 실행할 수 있습니다.씨앗!
내가 아주 좋아하기 시작한 한 가지는 마이그레이션을 실행한 다음during a release 시드를 실행하는 것입니다. 내 개발 및 프로덕션에서 필요한 데이터를 동일한 방식으로 설정할 수 있기 때문에 좋아합니다.
# db/seeds.rb
# Seed all the job levels, if it exists it won't add a new one.
JobLevel.find_or_create_by!(name: 'manager')
데이터베이스에 변경되지 않는 데이터를 넣는 이유는 무엇입니까?
실제로 dev/prod parity을 0으로 낮추기 위해 일부 데이터 비트가 데이터베이스에 전혀 속하는지 및 Plain Old Ruby Objects와 같은 것이 더 나은지 생각하기 시작했습니다.
JobLevel = Struct.new(:name, :enabled, keyword_init: true) do
alias enabled? enabled
def self.find(name)
all.find { |job_level| job_level.name == name }
end
def self.all
@all ||= [
new(name: 'executive', enabled: true),
new(name: 'manager', enabled: true),
]
end
end
이 접근 방식은 변경되지 않은 데이터로 데이터베이스를 쿼리하는 대신 메모리에 저장할 수 있기 때문에 제가 가장 좋아하는 방법입니다. 또한 모든 환경에서 동일할 강력한 피부여자와 함께 제공됩니다.
그렇다면 reset_column_information은 코드 냄새입니까?
그렇게 생각해요! 나는 이것이 "앞으로 몇 줄의 코드가 당신을 갉아먹을 것"이라는 지표라고 생각하며, 대부분의 경우 취할 수 있는 보다 안정적인 접근 방식이 있습니다.
Rubocop 경고가 적절하지 않다고 생각하지만 앞으로는 사용하지 않으려고 합니다.
Reference
이 문제에 관하여(reset_column_information은 코드 냄새입니까?), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/mikerogers0/is-resetcolumninformation-a-code-smell-81텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)