2011-08-23 26 views
5

Tôi có sau đây trong mô hình của tôi sử dụngvalidate và cập nhật thuộc tính đơn ray

attr_accessible :avatar, :email 

validates_presence_of :email 
has_attached_file :avatar # paperclip 

validates_attachment_size :avatar, 
          :less_than => 1.megabyte, 
          :message => 'Image cannot be larger than 1MB in size', 
          :if => Proc.new { |imports| !imports.avatar_file_name.blank? } 

thuộc một trong các bộ điều khiển của tôi, tôi CHỈ muốn cập nhật và kích hoạt các lĩnh vực avatar mà không cần cập nhật và xác nhận email.

Làm thế nào tôi có thể làm điều này?

ví dụ (điều này sẽ không hoạt động)

if @user.update_attributes(params[:user]) 
# do something... 
end 

Tôi cũng đã cố gắng với update_attribute('avatar', params[:user][:avatar]), nhưng điều đó sẽ bỏ qua kiểm chứng thực cho lĩnh vực avatar là tốt.

+1

Sao chép? http://stackoverflow.com/questions/457239/is-there-a-way-to-validate-a-specific-attribute-on-an-activerecord-without-instan/457313#457313 –

+0

không, tôi nghĩ rằng 'giả .valid? 'xác thực mọi thứ. Tôi đang tìm cách xác thực chỉ một thuộc tính. – Madhusudhan

Trả lời

13

Bạn có thể validate the attribute by hand và sử dụng update_attribute, rằng skips validation. Nếu bạn thêm this to your User:

def self.valid_attribute?(attr, value) 
    mock = self.new(attr => value) 
    if mock.valid? 
    true 
    else 
    !mock.errors.has_key?(attr) 
    end 
end 

Và sau đó cập nhật các thuộc tính thusly:

if(!User.valid_attribute?('avatar', params[:user][:avatar]) 
    # Complain or whatever. 
end 
@user.update_attribute('avatar', params[:user][:avatar]) 

Bạn sẽ nhận được thuộc tính duy nhất của bạn được cập nhật trong khi chỉ (bằng tay) xác nhận thuộc tính đó.

Nếu bạn nhìn vào cách hoạt động củacủa Milan Novota, bạn sẽ thấy rằng nó thực hiện xác thực và sau đó kiểm tra xem attr có vấn đề cụ thể hay không; không quan trọng nếu bất kỳ xác thực nào khác không thành công vì valid_attribute? chỉ xem xét các lỗi xác thực cho thuộc tính mà bạn quan tâm.

Nếu bạn định làm rất nhiều thứ này thì bạn có thể thêm phương thức vào Người dùng:

def update_just_this_one(attr, value) 
    raise "Bad #{attr}" if(!User.valid_attribute?(attr, value)) 
    self.update_attribute(attr, value) 
end 

và sử dụng để cập nhật thuộc tính duy nhất của bạn.

+0

điều này cũng sẽ kiểm tra xác thực email, không phải hình đại diện. – Madhusudhan

+0

@Madhusudhan: Bạn có thể thiết lập xác thực bằng tay và sử dụng 'update_attribute'. Vui lòng xem cập nhật của tôi. –

+0

yup đã giúp! cảm ơn! – Madhusudhan

1

Bạn đã thử đặt điều kiện trên validates_presence_of :email chưa?

http://ar.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#M000083

tùy chọn cấu hình:

nếu - Chỉ định một phương pháp, proc hoặc chuỗi gọi để xác định nếu xác nhận sẽ xảy ra (ví dụ: if =>: allow_validation, hoặc: if => Proc.new {| user | user.signup_step> 2}). Phương thức, proc hoặc chuỗi phải trả về hoặc đánh giá một giá trị đúng hoặc sai.

trừ khi - Chỉ định phương thức, proc hoặc chuỗi để gọi để xác định xem xác thực có nên xảy ra không (ví dụ: trừ =>: skip_validation hoặc: trừ => Proc.new {| user | user.signup_step < = 2 }). Phương thức, proc hoặc chuỗi phải trả về hoặc đánh giá một giá trị đúng hoặc sai.

1

Tôi giả sử bạn cần điều này, vì bạn có trình hướng dẫn nhiều bước, nơi bạn tải lên hình đại diện đầu tiên và email sẽ được điền sau.

Theo hiểu biết của tôi, với xác thực của bạn, chúng tôi thấy không có giải pháp làm việc tốt. Hoặc bạn xác thực tất cả hoặc cập nhật hình đại diện mà không cần xác thực.Nếu nó sẽ là một thuộc tính đơn giản, bạn có thể kiểm tra xem giá trị mới có vượt qua xác thực riêng biệt hay không và sau đó cập nhật mô hình mà không có xác thực (ví dụ: sử dụng update_attribute).

Tôi có thể đề nghị hai phương pháp thay thế có thể:

  • hoặc là bạn chắc chắn rằng e-mail luôn bước đầu tiên, mà tôi tin rằng không phải là một giải pháp xấu. Và sau đó, với mỗi lần lưu, xác thực được đáp ứng.
  • nếu không, hãy thay đổi xác thực. Tại sao bạn khai báo xác nhận trên một mô hình, nếu có các bản ghi trong cơ sở dữ liệu không đáp ứng được sự xác thực? Điều đó rất trực quan.

Vì vậy, tôi sẽ đề nghị một cái gì đó như thế này:

validate :presence_of_email_after_upload_avatar 

def presence_of_email_after_upload_avatar 
    # write some test, when the email should be present 
    if avatar.present? 
    errors.add(:email, "Email is required") unless email.present? 
    end 
end 

Hope this helps.

+0

errors.add (: email, "Email là bắt buộc") tạo lỗi = "Email Email là bắt buộc". Thay đổi "Email là bắt buộc" thành "bắt buộc" –

6

Điều kiện?

validates_presence_of :email, :if => :email_changed? 
1

Đây là giải pháp của tôi. Nó giữ nguyên hành vi tương tự hơn .valid? phương pháp, phù thủy trả về đúng hay sai, và thêm lỗi trên mô hình trên phù thủy nó được gọi là.

class MyModel < ActiveRecord::Base 
    def valid_attributes?(attributes) 
    mock = self.class.new(self.attributes) 
    mock.valid? 
    mock.errors.to_hash.select { |attribute| attributes.include? attribute }.each do |error_key, error_messages| 
     error_messages.each do |error_message| 
     self.errors.add(error_key, error_message) 
     end 
    end 

    self.errors.to_hash.empty? 
    end 
end 

> my_model.valid_attributes? [:first_name, :email] # => returns true if first_name and email is valid, returns false if at least one is not valid 
> my_modal.errors.messages # => now contain errors of the previous validation 
{'first_name' => ["can't be blank"]} 
Các vấn đề liên quan