코딩테스트를 보던 중 POST기능을 만들어 달라는 문제에서 아직 깊게 생각하지 못한 부분이 많다고 생각하여 좀 더 깊게 정리해보고자 작성했습니다!
def create
if user.create(user_params)
redirect_to root_path
else
render new
end
end
→ 실패할 경우 false가 반환값이 됩니다
def create
@user = user.create!(user_params)
redirect_to root_path
end
create!의 경우도 1,2,3 까지는 같습니다. 그러나 마지막 부분의 결과에서 차이가 있습니다.
1. ActiveRecord메소드 create(new + save)를 읽어들입니다
2. user_params에서 파라미터를 가저옵니다
3. create의 save부분에서 validation을 체크합니다
→ 성공할 경우 ActiveRecord오브젝트에 레코드를 실패할 경우 에러(예외)를 출력합니다
!
가 뭐야? 🧐Rails에서 !
는 예외를 발생시킨다는 의미로 사용됩니다
예를 들어
변수 이름을 지을 때도 메소드에서 에러를 발생시크는 메소드의 경우 !
를 마지막에 사용합니다(boolean이 return값이면?
를 사용하는 것처럼)
# 예외값을 갖는 경우
def validate_user!
raise StandardError if params[:name] == ''
rescue ActionController::BadRequest
render_404
end
save,create,update | save!,create!,update! | |
---|---|---|
ActiveRecord::RecordInvalid(validation) | return false | 예외 |
ActiveRecord::RecordNotSaved(callback) | return false | 예외 |
ActiveRecord::RecordNotUnique,ActiveRecord::StatementInvalid등 | 예외 | 예외 |
가볍게 정리하면 위에 표처럼 됩니다.
위에서 정리했던 내용과 조금 다른점은 NotUnique, StatementInvalid이 경우는 save의 경우에도 예외를 출력합니다
왜?🧐
ActiveRecord::RecordNotUnique의 경우, 데이터베이스가 고유성 제약 위반(Unique제약)을 발견한 경우 예외를 발생시키기 때문에 Rails쪽에서도 예외를 발생시킨다
ActiveRecord::StatementInvalid에러 경우도 RecordNotUnique와 비슷한 경우로 SQL구문에러가 발생한 경우에 해당한다.
DB관련에서 에러가 발생한 경우에는 Rails !
관계 없이 예외를 발생시키는 것 같다
로그를 한번 확인해보자
pry(main)> User.create(group_id: 8)
TRANSACTION (2.0ms)
BEGIN
User Create (4.6ms) INSERT INTO 생략 TRANSACTION (0.3ms)
ROLLBACK
ActiveRecord::NotNullViolation: PG::NotNullViolation: ERROR:
null value in column "컬럼" violates not-null constraint
scaffold을 사용한 경우로 정리해보았습니다
def create
@user = User.new(user_params)
respond_to do |format|
if @user.save
format.html { redirect_to @user, notice: "User was successfully created." }
format.json { render :show, status: :created, location: @user }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
end
이 경우 개인적으로 생각한 장점・단점의 경우는 아래와 같다
장점
단점
def create
return render status: :conflict if User.exists?(id: task_params[:id])
task = User.create!(user_params)
render json: user
rescue ActiveRecord::RecordInvalid
Rails.logger.error('RecordInvalidError 00정보가 없습니다')
render status: :bad_request
rescue StandardError
Rails.logger.error('StandardError')
render status: :internal_server_error
end
!가 없는 경우의 장점, 단점이 반대로 될 것 같다.
장점
단점
📃 비고
잘 나와있는 사이트가 있어서 공유합니다! 일본사이트인대 보는대는 딱히 문제가 없을 겁니다!
Rails HTTP Status의 심볼이 잘 나와있는 사이트(일본어)
transaction를 롤백 시키기 위해서는 저장하는 메소드에 !
를 사용할 필요가 있습니다. save의 경우 실패해도 false를 리턴하기 때문에 Transaction에서는 메소드가 문제가 없다고 판단하고 진행하기 때문입니다
ActiveRecord::Base.transaction do
user1.save!
user2.save # 에러 발생!
user3.save!
end
위에 코드에서 user2에서 에러가 발생해도 트랜잭션은 동작하지 않습니다!
이유는 위에 작성했던 것 처럼 예외가 발생하지 않기 때문입니다.
따라서 트랙잭션을 사용하는 경우에는 !
가 필요한점 꼭 주의해주세요!
정리 해보고 생각했던점은 무의식적으로 API를 작성하고 있었지만 중요한 것은 어떤 정보를 유저에게 보여주고 어떻게 에러 핸들링을 해 나갈지였던 것 같습니다.
정리를 해보며서 느낀점은 저희 회사에는 간단한 설정화면의 저장 기능이 아닌 이상 대부분 !
를 사용하여 에러 핸들링 하는게 많은 것 같습니다.
상황에 맞게 적절하게 코드를 작성하면 되고, 적절하게 메소드를 사용해나가면 좋을 것 같습니다!
틀린 부분이나 뭔가 추가 정보 같은 부분은 코멘트 환영입니다!