2017-01-01 17 views
6

Cần trợ giúp để hiểu mã này, như những gì tôi biết "< <" nối thêm vào bộ sưu tập nhưng ở đây nó lưu bản ghi một cách chính xác. .save phương pháp?đường ray - di chuyển sang trái "<<" nhà điều hành lưu bản ghi tự động

#user.rb 
has_many :saved_properties, through: :property_saves, source: :property 

#users_controller.rb 
def update 
    if @user.saved_properties << Property.find(params[:saved_property_id]) 
     render plain: "Property saved" 
end 

Trả lời

6

Có thể xem mã nguồn sẽ giúp bạn. Đây là dấu vết của tôi về tìm kiếm dựa trên phương pháp << trong activerecord:

def <<(*records) 
    proxy_association.concat(records) && self 
end 

rails/collection_proxy.rb at 5053d5251fb8c03e666f1f8b765464ec33e3066e · rails/rails · GitHub

def concat(*records) 
    records = records.flatten 
    if owner.new_record? 
    load_target 
    concat_records(records) 
    else 
    transaction { concat_records(records) } 
    end 
end 

rails/collection_association.rb at 5053d5251fb8c03e666f1f8b765464ec33e3066e · rails/rails · GitHub

def concat_records(records, should_raise = false) 
    result = true 

    records.each do |record| 
    raise_on_type_mismatch!(record) 
    add_to_target(record) do |rec| 
     result &&= insert_record(rec, true, should_raise) unless owner.new_record? 
    end 
    end 

    result && records 
end 

rails/collection_association.rb at 5053d5251fb8c03e666f1f8b765464ec33e3066e · rails/rails · GitHub

def insert_record(record, validate = true, raise = false) 
    set_owner_attributes(record) 
    set_inverse_instance(record) 

    if raise 
     record.save!(validate: validate) 
    else 
     record.save(validate: validate) 
    end 
    end 

https://github.com/rails/rails/blob/5053d5251fb8c03e666f1f8b765464ec33e3066e/activerecord/lib/active_record/associations/has_many_association.rb#L32

def insert_record(record, validate = true, raise = false) 
    ensure_not_nested 

    if record.new_record? || record.has_changes_to_save? 
     if raise 
     record.save!(validate: validate) 
     else 
     return unless record.save(validate: validate) 
     end 
    end 

    save_through_record(record) 

    record 
    end 

https://github.com/rails/rails/blob/5053d5251fb8c03e666f1f8b765464ec33e3066e/activerecord/lib/active_record/associations/has_many_through_association.rb#L38

Như bạn thấy, cuối cùng, nó gọi phương thức save.

Tuyên bố từ chối trách nhiệm: Tôi không quen với mã souse Rails, nhưng bạn có câu hỏi thú vị.

6

Trong has_manydocumentation nó nói:

Thêm một hoặc nhiều đối tượng đến việc thu thập bằng cách thiết lập ngoại phím của mình để khóa chính của bộ sưu tập. Lưu ý rằng thao tác này ngay lập tức kích hoạt cập nhật SQL mà không phải đợi để lưu hoặc cập nhật cuộc gọi trên đối tượng mẹ, trừ khi đối tượng mẹ là bản ghi mới.

2

Trong mối quan hệ has_many thông tin liên kết được lưu trong bản ghi đích. Điều này có nghĩa là << sẽ phải sửa đổi bản ghi đó để thêm bản ghi vào bộ này.

Có thể có ý định thuận tiện, ActiveRecord tự động lưu các mục này cho bạn khi thực hiện gán nếu gán thành công. Ngoại lệ dành cho các bản ghi mới, bản ghi mà chúng được liên kết với không có bất kỳ số nhận dạng nào để bị trễ. Chúng được lưu khi bản ghi chúng được liên kết với cuối cùng được tạo ra.

Điều này có thể hơi khó hiểu, có lẽ không mong muốn, nhưng đó thực sự là điều bạn muốn xảy ra 99% thời gian. Nếu bạn không muốn điều đó xảy ra, bạn nên thao tác liên kết theo cách thủ công:

property = Property.find(params[:saved_property_id]) 
property.user = @user 
property.save! 

Về cơ bản tương đương nhưng có nhiều chi tiết hơn.

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