2012-03-06 11 views
7

Trong ứng dụng của mình, đôi khi tôi tạo Người dùng đang bay và email của người dùng phải là định dạng hợp lệ và là duy nhất.đường ray 3.1: cách ứng dụng có thể xử lý các 'lý do' khác nhau cho ActiveRecord :: RecordInvalid (ví dụ: trùng lặp và lỗi xác thực)

Tôi muốn chuyển hướng đến các địa điểm khác nhau tùy thuộc vào việc xác thực mà gây ra lỗi được tăng lên: định dạng không hợp lệ so với trùng lặp.

Trong mã của tôi, tôi có

begin 
     user.save! 
     flash[:notice] = "Created new user #{email} with password #{password}" 

    rescue ActiveRecord::RecordInvalid => e 
     flash[:alert] = "Failed to create account because #{e.message}" 
     redirect_to SOMEPLACE 
    end 

Nếu email là định dạng không hợp lệ (chẳng hạn như "user @ dụ") e.message là "Validation thất bại: Email không hợp lệ"

Nếu email đã tồn tại trong bảng, e.message là "Xác thực không thành công: Email đã được thực hiện"

Tôi ghét ý tưởng phân tích văn bản e.message để xác định lý do ... có cách nào tốt hơn cho trình xử lý cứu hộ không để phát hiện nguyên nhân cơ bản của một ngoại lệ ActiveRecord :: RecordInvalid w như ném?

P.S. Tôi biết trong ví dụ này tôi chỉ có thể kiểm tra trước email đã tồn tại trước khi thực hiện lưu, nhưng tôi đang cố gắng hiểu giải pháp chung để phát hiện và hành động trên các lỗi xác thực khác nhau ném cùng một ngoại lệ.

+1

Trên thực tế không thể đơn giản kiểm tra trước email đã tồn tại, xác thực tính duy nhất của ActiveRecord phải tuân theo các điều kiện chủng tộc và bị phá vỡ bởi thiết kế.Bạn phải có một ràng buộc duy nhất bên trong cơ sở dữ liệu của mình và bạn phải chuẩn bị o đối phó với ngoại lệ là nó sẽ tăng (hoặc từ '.save' hoặc' .save! '). –

Trả lời

1

Các Rails cách tiêu chuẩn để làm điều này là không sử dụng các nhà điều hành bang, trong đó đặt ra một ngoại lệ, nhưng để sử dụng tiêu chuẩn tiết kiệm phương pháp và kiểm tra xem nó trở lại đúng hay sai:

if @user.save 
    flash[:notice] = "User created." 
    redirect_to :action => :index 
else 
    flash[:alert] = "User could not be created." 
    render :action => :new 
end 

Và trong bạn chế độ xem tạo người dùng:

<% if @user.errors.any? %> 
    <ul> 
    <% @user.errors.full_messages.each do |msg| %> 
     <li><%= msg %></li> 
    <% end %> 
    </ul> 
<% end %> 
+0

Nhưng điều đó không cho bạn biết lý do tại sao lưu không thành công. Nếu bạn có một ràng buộc duy nhất bên trong cơ sở dữ liệu của mình (điều mà bạn cần phải xác nhận tính duy nhất của AR là tùy thuộc vào điều kiện chủng tộc) thì bạn có thể có 'x.valid?' Là true nhưng cả 'x.save' và' x.save! 'Có thể tăng ngoại lệ vì ràng buộc của cơ sở dữ liệu đã bị vi phạm. –

0

Nếu tôi hiểu những gì bạn đang cố gắng làm chính xác, một cách để làm điều này sẽ chỉ là khẳng định sự hiện diện của lỗi ở cấp trường. ví dụ.

if user.errors[:field_name].present? 
    redirect_to path_for_field_name_error 
end 

Ngoài ra, bạn xác định một số bản đồ về những gì các lĩnh vực chuyển hướng nơi như một hằng số (ví dụ REDIRECT_PATHS trong trường hợp này bạn kết thúc với một cái gì đó như:

redirect_to REDIRECT_PATHS[field_name] if user.errors[:field_name].present? 

nơi bạn có thể chỉ vòng qua field_name s

+0

Trong ví dụ của tôi, nhiều lỗi có thể xảy ra cho cùng một địa chỉ email của trường có thể không hợp lệ hoặc đã được sử dụng, chẳng hạn. – jpwynn

+0

K. Nếu bạn bằng cách nào đó có thể sử dụng các built-in ActiveRecord để xử lý mọi thứ không phải là ràng buộc duy nhất do DB điều khiển (mà @mu quá ngắn chỉ ra chính xác không phải lúc nào cũng hoạt động như mong đợi), thì bạn có thể kiểm tra chống lại '.valid? 'và bóc các lỗi theo cách đó, ngoại trừ ràng buộc duy nhất này. Tất nhiên, nếu bạn có nhiều ràng buộc trên các trường khác, nó vẫn là một vấn đề và quay trở lại phân tích cú pháp chuỗi. Chúc may mắn, hy vọng đó là hữu ích? –