Ruby ve / veya Rails'te özel hata türleri nerede tanımlanır?


149

Ruby kitaplığında (gem) veya Ruby on Rails uygulamasında özel hata türlerini tanımlamak için en iyi uygulama var mı? özellikle:

  1. Projede yapısal olarak nereye aitler? İlgili modül / sınıf tanımıyla işaretlenmiş ayrı bir dosya, başka bir yerde mi?
  2. Ne zaman kurmak herhangi konvansiyonlar var mıdır etmek ve ne zaman değil , yeni bir hata türünü oluşturmak?

Farklı kütüphanelerin işleri yapmanın farklı yolları vardır ve gerçek kalıpları fark etmedim. Bazı kütüphaneler her zaman özel hata türlerini kullanırken diğerleri hiç kullanmaz; bazılarının StandardError'ı genişleten tüm hataları vardır, diğerleri ise iç içe hiyerarşileri içerir; bazıları sadece boş sınıf tanımlarıdır, diğerleri her türlü zekice numaraya sahiptir.

Oh, ve ben sadece bu "hata türleri" demek biraz belirsiz gibi hissediyorum, demek istediğim bu:

class AuthenticationError < StandardError; end
class InvalidUsername < AuthenticationError; end

Yanıtlar:


219

Taşlar için

İstisnaları bu şekilde tanımladığınızı birçok kez gördüm:

gem_dir / lib / gem_name / exceptions.rb

ve şu şekilde tanımlanır:

module GemName

  class AuthenticationError < StandardError; end
  class InvalidUsername < AuthenticationError; end

end

bunun bir örneği httparty'de böyle bir şey olabilir

Ruby on Rails için

Bunları lib / klasörünüze, exceptions.rb adlı bir dosyanın altına koyun, bu şuna benzer:

module Exceptions
  class AuthenticationError < StandardError; end
  class InvalidUsername < AuthenticationError; end
end

ve şu şekilde kullanırsınız:

raise Exceptions::InvalidUsername

Taşlar için, istisna dosyasını da eklemeniz gerekebilir. Yine bu örneğe bakın httparty: github.com/jnunemaker/httparty/blob/…
Jason Swett

37
Neden bunları Exceptionsmodüle yerleştirmelisiniz?
ABMagil

13
Bu /libhatalar için bir yer olmayabilir düşünüyorum . Onlar çok uygulamaya özgü ve ben koyuyorum /libkod diğer uygulamalarda yeniden kullanılabilecek kod olması gerektiği izlenimi altında .
wuliwong

1
Ruby on Rails talimatları benim için çalışmadı - tipik olarak bu yeni dosyayı yüklemek için ek bir adım gerekli mi?
Meekohi

1
@ABMagil başka türlü Unable to autoload constant Exceptions, expected /app/lib/exceptions.rb to define itbence istisna başına bir sınıf olurdu
ryan2johnson9

25

Projenizde uyumlu kaynak dosyalara sahip olmak için, sınıfta onları atabilecek ve başka hiçbir yerde hatalar tanımlamanız gerektiğini düşünüyorum.

Bazı heirarchy yardımcı olabilir - ad alanları, gereksiz dizeleri tür adlarının dışında tutmakta iyidir - ancak bu daha çok bir zevk meselesidir - uygulamanızda farklılaştırmak için kullandığınız en az bir özel istisna türüne sahip olmanız koşuluyla, denize girmek zorunda kalmazsınız. 'kasıtlı' ve 'kazayla' istisna durumları arasında.


8
Teoride haklı olsanız da, tamamen farklı durumlarda aynı hata çeşitli sınıflar tarafından ortaya çıkartıldığında ne olur?
Alain

1
@Alain Neden İstisnalar / Hatalar modülünde birden fazla sınıf tarafından kullanılan bu hataları tanımlamıyorsunuz, ancak diğerlerini tanımlayan tek bir sınıfta tanımlanmış halde bırakıyorsunuz?
Scott W

@ScottW, Bu durumda, kontrol etmeyi hatırlamak için geliştiriciye güveniyoruz.
Josh Saint Jacque

22

raylarda app/errorsdizin yapabilirsiniz

# app/errors/foo_error.rb
class FooError < StandardError; end

baharı / sunucuyu yeniden başlat ve onu al


Bu istisnaları nasıl dile getirmeliyim?
Nikhil Wagh

@NikhilWagh ya raise FooError, "Example message..."daraise FooError.new("Example message...")
schpet

13

Bu eski bir soru, ancak Rails'te hata mesajlarını ekleme, test etme ve bunu ActiveRecordmodellerle nasıl ele alacağım gibi özel hataları nasıl ele aldığımı paylaşmak istedim .

Özel Hata Oluşturma

class MyClass
  # create a custome error
  class MissingRequirement < StandardError; end

  def my_instance_method
    raise MyClass::MissingRequirement, "My error msg" unless true   
  end
end

Test (en küçük)

test "should raise MissingRequirement if ____ is missing"
  # should raise an error
  error = assert_raises(MyClass::MissingRequirement) {
    MyClass.new.my_instance_method
  }

  assert error.message = "My error msg"
end

ActiveRecord ile

Bir ActiveRecordmodelle çalışıyorsanız , popüler bir modelin, aşağıda açıklandığı gibi modele bir hata eklemek olduğunu belirtmek gerekir, böylece doğrulamalarınız başarısız olur:

def MyModel < ActiveRecord::Base
  validate :code_does_not_contain_hyphens

  def code_does_not_contain_hyphens
    errors.add(:code, "cannot contain hyphens") if code.include?("-")
  end
end

Doğrulamalar çalıştırıldığında, bu yöntem ActiveRecord'un ActiveRecord::RecordInvalidhata sınıfına geri döner ve doğrulamaların başarısız olmasına neden olur.

Bu yardımcı olur umarım!


9

Otomatik yüklemenin, çoklu özel hata sınıfları için Rails 4.1.10'da beklendiği gibi çalışmasını sağlamak için her biri için ayrı dosyalar belirtmek isteyeceksiniz. Bu, dinamik olarak yeniden yüklenmesi ile geliştirme aşamasında çalışmalıdır.

Son bir projede hataları bu şekilde kurarım:

İçinde lib/app_name/error/base.rb

module AppName
    module Error
        class Base < StandardError; end
    end
end

ve sonraki özel hatalarda, lib/app_name/error/bad_stuff.rb

module AppName
    module Error
        class BadStuff < ::AppName::Error::Base; end
    end
end

Daha sonra hatalarınızı aşağıdaki yollarla arayabilmelisiniz:

 raise AppName::Error::BadStuff.new("Bad stuff just happened")

Ve her yeni hata için ayrı bir dosya istemiyorsanız, hepsini koyunlib/app_name/error.rb
jlhonora

Bir uninitialized constant MyController::AppName. Denetleyicimde zam arıyorum
Nikhil Wagh
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.