2008-12-11 44 views
20

Tôi có ứng dụng Rails cho phép người dùng xây dựng truy vấn cơ sở dữ liệu bằng cách điền vào biểu mẫu mở rộng. Tôi tự hỏi thực hành tốt nhất để kiểm tra các tham số biểu mẫu trong Rails. Trước đây, tôi đã có results phương pháp của tôi (một trong những mà hình thức nộp) làm như sau:Xác thực biểu mẫu đường ray

if params[:name] && !params[:name].blank? 
    @name = params[:name] 
else 
    flash[:error] = 'You must give a name' 
    redirect_to :action => 'index' 
    return 
end 

Nhưng đối với một số lĩnh vực hình thức, nhìn thấy điều này lặp đi lặp lại cho mỗi người nhận được mệt mỏi. Tôi có thể không chỉ gắn bó tất cả chúng trong một số vòng lặp để kiểm tra đối với từng lĩnh vực, bởi vì các lĩnh vực được thiết lập khác nhau:

  • một chìa khóa duy nhất: params[:name]
  • một khóa và một sub-key: params[:image][:font_size]
  • chỉ mong đợi một số lĩnh vực hình thức để được điền nếu lĩnh vực khác được thành lập

vv Đây cũng là lặp đi lặp lại, bởi vì tôi đã thiết lập flash[:error] cho mỗi thiếu tham số/không hợp lệ, và chuyển hướng đến cùng một URL cho mỗi một. Tôi chuyển sang sử dụng before_filter để kiểm tra tất cả thông số biểu mẫu cần thiết và chỉ trả về true nếu mọi thứ đều ổn. Sau đó, các phương pháp results tôi vẫn tiếp tục, và các biến chỉ là giao phẳng ra, không có kiểm tra liên quan đến:

@name = params[:name] 

Trong phương pháp validate_form tôi, tôi có phần mã lệnh như sau:

if (
    params[:analysis_type][:to_s] == 'development' || 
    params[:results_to_generate].include?('graph') 
) 
    {:graph_type => :to_s, :graph_width => :to_s, 
    :theme => :to_s}.each do |key, sub_key| 
    unless params[key] && params[key][sub_key] 
     flash[:error] = "Cannot leave '#{Inflector.humanize(key)}' blank" 
     redirect_to(url) 
     return false 
    end 
    end 
end 

tôi chỉ là tự hỏi nếu tôi đang đi về điều này một cách tốt nhất, hoặc nếu tôi thiếu một cái gì đó rõ ràng khi nói đến xác nhận tham số. Tôi lo lắng điều này vẫn không phải là kỹ thuật hiệu quả nhất, bởi vì tôi có một số khối nơi tôi gán một giá trị cho flash[:error], sau đó chuyển hướng đến cùng một URL, sau đó trả về false.

Sửa để làm rõ: Lý do tôi không có xác nhận này trong mô hình (s) hiện đang là vì hai lý do:

  • Tôi không cố gắng để thu thập dữ liệu từ người dùng để tạo hoặc cập nhật một hàng trong cơ sở dữ liệu. Không có dữ liệu nào mà người dùng gửi được lưu sau khi họ đăng xuất. Tất cả đều được sử dụng ngay khi họ gửi nó để tìm kiếm cơ sở dữ liệu và tạo ra một số thứ.
  • Biểu mẫu truy vấn lấy dữ liệu liên quan đến một số mô hình và phải mất dữ liệu khác không liên quan đến mô hình. Ví dụ. loại biểu đồ và chủ đề như được hiển thị ở trên không kết nối với bất kỳ mô hình nào, chúng chỉ truyền đạt thông tin về cách người dùng muốn hiển thị kết quả của mình.

Edit để hiển thị cải tiến kỹ thuật: Tôi tận dụng ngoại lệ ứng dụng cụ thể bây giờ, nhờ Jamis Buck Raising the Right Exception article. Ví dụ:

def results 
    if params[:name] && !params[:name].blank? 
    @name = params[:name] 
    else 
    raise MyApp::MissingFieldError 
    end 

    if params[:age] && !params[:age].blank? && params[:age].numeric? 
    @age = params[:age].to_i 
    else 
    raise MyApp::MissingFieldError 
    end 
rescue MyApp::MissingFieldError => err 
    flash[:error] = "Invalid form submission: #{err.clean_message}" 
    redirect_to :action => 'index' 
end 
+0

Tôi nghĩ bạn không phải sử dụng thông số [: name] và! Params [: name] .blank? trong các điều khoản của bạn. ! params [: name] .blank? Là đủ. params [: name] trả về false nếu nó là nil (không có tham số như vậy) và params [: name] .blank? trả về true nếu nó là nil hoặc trống. – klew

+0

Bạn nhận được NoMethodError. Tôi có thể ghi đè lên NilClass để thêm #blank? với nó, tôi cho là vậy. irb (chính): 002: 0> params = {: a => 1,: b => 2,: c => 3} => {: c => 3,: a => 1,: b => 2} irb (chính): 003: 0>! Params [: name] .blank? NoMethodError: phương thức chưa xác định 'trống? ' cho nil: NilClass từ (irb): 3 –

+0

Không có Ruby ở đây, chỉ Rails. * Thẻ đã xóa * – Nakilon

Trả lời

25

Bạn có thể thử active_form (http://github.com/cs/active_form/tree/master/lib/active_form.rb) - chỉ ActiveRecord trừ nội dung cơ sở dữ liệu. Bằng cách này, bạn có thể sử dụng tất cả các công cụ xác thực của AR và xử lý biểu mẫu của bạn giống như bất kỳ mô hình nào khác.

class MyForm < ActiveForm 
    validates_presence_of :name 
    validates_presence_of :graph_size, :if => # ...blah blah 
end 

form = MyForm.new(params[:form]) 
form.validate 
form.errors 
+0

Có phải 'validates_presence_of: name' là một bí danh cho' validates: name, presence: true' không? Tôi đã chỉ nhìn thấy sau này trong hướng dẫn Rails. – Dennis

+1

Để trả lời câu hỏi của riêng tôi, cách thứ hai là một cách mới để thực hiện các xác nhận được giới thiệu trong Rails 3. http://thelucid.com/2010/01/08/sexy-validation-in-edge-rails-rails-3/ – Dennis

6

Có vẻ như bạn đang thực hiện xác thực trong bộ điều khiển, hãy thử đặt trong mô hình, nó phù hợp hơn với loại điều đó.

+4

Cũng được đề xuất trong [hướng dẫn] (http://guides.rubyonrails.org/active_record_validations_callbacks.html): "Xác thực cấp điều khiển có thể hấp dẫn để sử dụng, nhưng thường trở nên khó sử dụng và khó kiểm tra và Bất cứ khi nào có thể, đó là một ý tưởng hay để [giữ cho bộ điều khiển của bạn gầy] (http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model), vì nó sẽ làm cho ứng dụng của bạn trở thành một niềm vui để làm việc trong thời gian dài. " –

2

Nếu bạn đã giải quyết vấn đề một lần nữa hôm nay, bạn có thể tạo ra một mô hình cho các thiết lập tham số truy vấn và sử dụng Rails' được xây dựng trong kiểm chứng thực, Rails 3 làm này dễ dàng hơn rất nhiều với ActiveModel :: validations thấy this post.

Các vấn đề liên quan