2014-08-31 5 views
1

여기에 문제가 있습니다. 사용자 모델, 주문 모델 및 주소 모델이 있다고 가정 해 보겠습니다.레일 : 연결시 필드 유효성 검사

class User < ActiveRecord::Base 
    belongs_to :address, :foreign_key => :address_id, :class_name => "Address" 
end 

class Order < ActiveRecord::Base 
    belongs_to :address, :foreign_key => :address_id, :class_name => "Address" 
end 

class Address < ActiveRecord::Base 
    attr_accessible :email, :address 
end 

이제 사용자 모델에서 주소 모델의 전자 메일 필드를 확인하고 싶습니다.

하지만 Order 모델에서 주소 모델의 주소 필드 만 유효성을 검사하고 싶습니다.

나는이 시도했다 :

class User < ActiveRecord::Base 
    belongs_to :address, :foreign_key => :address_id, :class_name => "Address" 
    validate :address_fields 

    def address_fields 
     self.address.errors.add 'email' unless self.address.email.present? 
    end 
end 

그것은 콘솔에서 작업을 수행하지만 단순한 형태의 오류가 표시되지 않으며 표시되지 않습니다.

제대로 할 생각이 있으십니까?

답변

1

당신이 가까이있는 것처럼 들리지만,하려는 일에 따라 약간의 미묘한 차이가 있습니다.

일반적으로 레일즈는 모델 중심 유효성 검사를 위해 설정됩니다. 즉, 모델이 유효하거나 유효하지 않습니다. Rails는 검증중인 모델에 유효성 검사가 제공 될 것을 기대하고 있으며,이를 돕기 위해 validates_associated validator을 제공합니다. 다음은 Address에 몇 가지 규칙을 적용하고 UserOrder 모델에 저장할 때 유효성을 검사하는 예제입니다.

class User < ActiveRecord::Base 
    belongs_to :address 
    validates_associated :address 
end 

class Order < ActiveRecord::Base 
    belongs_to :address 
    validates_associated :address 
end 

class Address < ActiveRecord::Base 
    has_many :users 
    has_many :orders 
    attr_accessible :email, :address 

    # This isn't a good regex for validating email addresses, it's just an example 
    validates :email, format: { with: /^[A-z0-9][email protected][A-z0-9.]+.[A-z]$/ } 
    validates :address, presence: true 
end 

또한 검증에 :if:unless 옵션을 사용하여 conditional validations 수 있습니다. 당신의 Address 많은 사용자가 할 수있는 경우

validates :phone_number, presence: true, if: :us_address? 
def us_address? 
    country == "United States" 
end 

(예를 들어, 두 명 이상이 주문할 수 있습니다 당신이 미국 Address의 경우에만 Address에 전화 번호가 필요하기를 원한다면 예를 들어, 당신이 사용할 수 (고객이 두 번 이상 주문할 수 있기 때문에) 많은 주문을 할 수 있으므로 요청한 규칙을 준수하는 Address 모델의 조건부 유효성 검사를 작성하기가 어렵습니다. 마음에 봄이되는 몇 가지 대안이 있습니다.

  • 이메일을 User 모델에 대신 저장하십시오. 건물에 이메일을 보낼 수는 없으므로 거기에는 더 많은 의미가 있습니다. 인보이스를 재현 할 수 있도록 사용자의 이메일 주소를 스냅 샷으로 표시하려면 에 confirmation_sent_to_email 필드를 포함시켜야합니다.
  • OrderAddressUserAddress의 두 가지 모델이 있습니다. 그들은 서로 다른 유효성 검사 규칙을 가질 수 있으며, 응용 프로그램에서 어떤 유형을 다루고 있는지 명확 해집니다. 주소 세부 정보 만 보유하고있는 Address 모델을 여전히 가지고 있으며 OrderAddressUserAddress 모델과 적절하게 연결할 수 있습니다.
+0

감사합니다. 두 가지 제안은 약간 지저분한 것 같지만 나에게 아이디어를주었습니다. 주소 모델 인 OrderAddress와 UserAddress에 대해 두 개의 서브 클래스를 갖는 방법. 유일한 차이점은 검증 일 것입니다. 그게 효과가 있니? – bymannan

+0

당신은 그렇게 할 수 있습니다 - 레일즈는 당신이 [단일 테이블 상속] (http://api.rubyonrails.org/classes/ActiveRecord/Base.html#class-ActiveRecord::Base-label-Single)을 사용하여 그렇게하고 싶습니다. + 테이블 + 상속) -하지만 나는 여전히 옵션 1을 선호합니다. STI를 사용하여 DB 수준의 제약 조건을 추가하는 것이 더 어려울 것이며, 데이터를 확인하고 그것이 괜찮은지 아닌지 판단하는 것이 더 어렵습니다. –

1

간단한 대답입니다.

user.address 대신 user에 오류를 추가하십시오.

class User < ActiveRecord::Base 
    def address_fields 
     self.errors.add 'email' unless self.address.email.present? 
    end 
end 

그러면 단순한 사용자 양식에서 오류를 볼 수 있습니다.

아니면 사용자가이 같이 형성뿐만 아니라 user.errors 및 user.address.errors을 처리하기 위해 업데이트 할 수 있습니다 대답에 대한

<% if @user.errors.any? || @user.address.errors.any?%> 
    <div id="error_explanation"> 
     <h2><%= pluralize(@user.errors.count + @user.address.errors.count, "error") %> prohibited this user from being saved:</h2> 

     <ul> 
     <% @user.errors.full_messages.each do |msg| %> 
     <li><%= msg %></li> 
     <% end %> 
     </ul> 
     <ul> 
     <% @user.address.errors.full_messages.each do |msg| %> 
     <li><%= msg %></li> 
     <% end %> 
     </ul> 
    </div> 
    <% end %> 
+0

이 문제는 이메일 필드 옆에있는 것이 아니라 사용자 필드에 오류가 표시된다는 것입니다. – bymannan

+0

이것은 양식의 오류 처리 방법에 따라 다릅니다. 사용자 폼에서 대개'<% if @ user.errors.any? %>'. 더 많은 에러를 보여주고 싶다면'<% if @ user.errors.any? || user.address.errors.any? %>'. 내 업데이 트를 참조하십시오. –