Rails update_attribut mà không lưu?


386

Có cách nào khác để update_attribut không lưu bản ghi không?

Vì vậy, tôi có thể làm một cái gì đó như:

@car = Car.new(:make => 'GMC')
#other processing
@car.update_attributes(:model => 'Sierra', :year => "2012", :looks => "Super Sexy, wanna make love to it")
#other processing
@car.save

BTW, tôi biết tôi có thể @car.model = 'Sierra', nhưng tôi muốn cập nhật tất cả chúng trên một dòng.


bạn có ý nghĩa gì "không lưu hồ sơ"?
Anatoly

update_attribut lưu mô hình DB. Tôi tự hỏi nếu có một phương pháp tương tự mà không.
tybro0103

3
thuộc tính phương pháp không phá hủy. Xem API để biết chi tiết
Anatoly

3
Bạn có thể sử dụng update_column (tên, giá trị) Cập nhật một thuộc tính duy nhất của một đối tượng, mà không cần gọi lưu. 1. Xác nhận được bỏ qua. 2. Gọi lại được bỏ qua. 3. cột update_at / update_on không được cập nhật nếu cột đó khả dụng. apidock.com/rails/ActiveRecord/Persistence/update_column
Antoine

10
Đối với 3.1+, hãy sử dụng assign_attributes apidock.com/rails/ActiveRecord/Base/assign_attribut
elado

Câu trả lời:


597

Tôi tin rằng những gì bạn đang tìm kiếm là assign_attributes.

Về cơ bản, nó giống như update_attribut nhưng nó không lưu bản ghi:

class User < ActiveRecord::Base
  attr_accessible :name
  attr_accessible :name, :is_admin, :as => :admin
end

user = User.new
user.assign_attributes({ :name => 'Josh', :is_admin => true }) # Raises an ActiveModel::MassAssignmentSecurity::Error
user.assign_attributes({ :name => 'Bob'})
user.name        # => "Bob"
user.is_admin?   # => false
user.new_record? # => true

Ví dụ của bạn là một chút sai lệch vì bạn đã không dán dòng này từ mô hình : attr_accessible :is_admin, :as => :admin;)
Robin

@Robin Hoặc đơn giản là : attr_protected :is_admin. Hoặc: attr_accessible :nameĐiểm chính là trong ví dụ này ,: is_admin được bảo vệ. Tôi cũng nên lưu ý rằng việc cố gắng gán khối lượng một thuộc tính được bảo vệ .assign_attributesthực sự làm tăng một ActiveModel::MassAssignmentSecurity::Error, mặc dù điều đó không được hiển thị trong ví dụ.
Ajedi32

Vâng, nhưng dòng của tôi là từ tài liệu bạn liên kết đến. Tôi chỉ nói rằng bạn nên sao chép / dán toàn bộ ví dụ. Nhưng vâng, bạn chỉ có thể nói rằng nó được bảo vệ.
Robin

@Robin Tôi sẽ cập nhật ví dụ để cụ thể hơn một chút. Ví dụ trong các tài liệu cũng hơi sai lệch, vì nó không đề cập đến việc user.assign_attributes({ :name => 'Josh', :is_admin => true })làm tăng thông báo lỗi và không thực sự đặt thuộc tính tên người dùng.
Ajedi32

7
gán_attribut có sẵn từ Rails 3.1 trở đi, vì vậy bạn không thể sử dụng nó nếu bạn vẫn đang chạy phiên bản Rails cũ.
Haegin

174

Bạn có thể sử dụng assign_attributeshoặc attributes=(chúng giống nhau)

Phương pháp cập nhật bảng cheat (cho Rails 6):

  • update= assign_attributes+save
  • attributes= = bí danh của assign_attributes
  • update_attributes = không dùng nữa, bí danh của update

Nguồn:
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribution_assocate .rb

Một bảng cheat khác:
http://www.davidverhasselt.com/set-attribut-in-activerecord/#cheat-sheet


1
Rõ ràng và ngắn gọn. Cảm ơn.
freemanoid

1
trong trường hợp .attribut = val, nếu mô hình của bạn has_one và ac accept_nested_attribut_for một mô hình khác, việc chuyển that_model_attribut (không có id) sẽ xóa mô hình has_one hiện tại, ngay cả khi bạn không kiên trì (ví dụ như lưu). Nhưng gán_attribut không hành xử như vậy.
ClassyPimp

65

Bạn có thể sử dụng phương thức 'thuộc tính':

@car.attributes = {:model => 'Sierra', :years => '1990', :looks => 'Sexy'}

Nguồn: http://api.rubyonrails.org/groupes/ActiveRecord/Base.html

các thuộc tính = (new_attribut, Guard_protected_attribut = true) Cho phép bạn đặt tất cả các thuộc tính cùng một lúc bằng cách chuyển vào hàm băm với các khóa khớp với tên thuộc tính (một lần nữa khớp với tên cột).

Nếu Guard_protected_attribut là true (mặc định), thì các thuộc tính nhạy cảm có thể được bảo vệ khỏi hình thức gán khối này bằng cách sử dụng macro attr_protected. Hoặc bạn có thể chỉ định thay thế các thuộc tính nào có thể được truy cập bằng macro attr_accessible. Sau đó, tất cả các thuộc tính không được bao gồm trong đó sẽ không được phép gán khối lượng.

class User < ActiveRecord::Base
  attr_protected :is_admin
end

user = User.new
user.attributes = { :username => 'Phusion', :is_admin => true }
user.username   # => "Phusion"
user.is_admin?  # => false

user.send(:attributes=, { :username => 'Phusion', :is_admin => true }, false)
user.is_admin?  # => true

7

Để gán khối lượng giá trị cho mô hình ActiveRecord mà không lưu, hãy sử dụng assign_attributeshoặc attributes=phương thức. Các phương thức này có sẵn trong Rails 3 và mới hơn. Tuy nhiên, có những khác biệt nhỏ và các vấn đề liên quan đến phiên bản cần chú ý.

Cả hai phương pháp đều tuân theo cách sử dụng này:

@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }

@user.attributes = { model: "Sierra", year: "2012", looks: "Sexy" }

Lưu ý rằng không phương thức nào sẽ thực hiện xác nhận hoặc thực hiện các cuộc gọi lại; gọi lại và xác nhận sẽ xảy ra khi saveđược gọi.

Đường ray 3

attributes=khác một chút so với assign_attributestrong Rails 3. attributes=sẽ kiểm tra xem đối số được truyền cho nó có phải là Hash không và trả về ngay lập tức nếu không;assign_attributeskhông có kiểm tra Hash như vậy. Xem tài liệu API phân bổ thuộc tính ActiveRecord để biếtattributes= .

Mã không hợp lệ sau đây sẽ âm thầm thất bại bằng cách đơn giản trả về mà không đặt các thuộc tính:

@user.attributes = [ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ]

attributes= sẽ âm thầm hành xử như thể các bài tập đã được thực hiện thành công, khi thực sự, chúng không.

Mã không hợp lệ này sẽ đưa ra một ngoại lệ khi assign_attributescố gắng xâu chuỗi các khóa băm của mảng kèm theo:

@user.assign_attributes([ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ])

assign_attributessẽ đưa ra một NoMethodErrorngoại lệ chostringify_keys , chỉ ra rằng đối số đầu tiên không phải là Hash. Bản thân ngoại lệ không có nhiều thông tin về nguyên nhân thực tế, nhưng thực tế là một ngoại lệ xảy ra là rất quan trọng.

Sự khác biệt duy nhất giữa các trường hợp này là phương pháp được sử dụng để gán khối lượng: attributes= âm thầm thành công và assign_attributesđưa ra một ngoại lệ để thông báo rằng đã xảy ra lỗi.

Các ví dụ này có thể có vẻ khó hiểu và ở một mức độ nào đó, nhưng loại lỗi này có thể dễ dàng xảy ra khi chuyển đổi dữ liệu từ API hoặc thậm chí chỉ sử dụng một loạt chuyển đổi dữ liệu và quên Hash[] kết quả cuối cùng .map. Duy trì một số mã 50 dòng ở trên và 3 hàm bị xóa khỏi gán thuộc tính của bạn và bạn đã có một công thức cho sự thất bại.

Bài học với Rails 3 là thế này: luôn luôn sử dụngassign_attributes thay vì attributes=.

Đường ray 4

Trong Rails 4, attributes=chỉ đơn giản là một bí danh assign_attributes. Xem tài liệu API phân bổ thuộc tính ActiveRecord để biếtattributes= .

Với Rails 4, một trong hai phương pháp có thể được sử dụng thay thế cho nhau. Việc không vượt qua Hash là đối số đầu tiên sẽ dẫn đến một ngoại lệ rất hữu ích:ArgumentError: When assigning attributes, you must pass a hash as an argument.

Xác nhận

Nếu bạn đang thực hiện các bài tập trước chuyến bay để chuẩn bị cho một save, bạn cũng có thể quan tâm đến việc xác nhận trước khi lưu. Bạn có thể sử dụng valid?invalid?phương pháp cho việc này. Cả hai trả về giá trị boolean. valid?trả về true nếu mô hình chưa được lưu vượt qua tất cả các xác nhận hoặc false nếu nó không. invalid?chỉ đơn giản là nghịch đảo củavalid?

valid? có thể được sử dụng như thế này:

@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }.valid?

Điều này sẽ cung cấp cho bạn khả năng xử lý bất kỳ vấn đề xác nhận trước khi gọi save.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.