2011-01-19 29 views
15

Đã dành cả ngày trên Google nhưng không thể tìm thấy câu trả lời. : \Đường ray: Có và thuộc về nhiều (HABTM) - tạo liên kết mà không tạo các bản ghi khác

Tôi có mối quan hệ HABTM giữa Người dùng và Core_Values.

class CoreValue < ActiveRecord::Base 
    has_and_belongs_to_many :users 

class User < ActiveRecord::Base 
    has_and_belongs_to_many :core_values 

Trong điều khiển của tôi, tôi cần phải làm hai việc riêng biệt:

  1. Nếu một CoreValue không tồn tại, tạo một hình mới và kết hợp nó với một người dùng id cho trước, và
  2. Giả Tôi biết một CoreValue cụ thể đã tồn tại, tạo liên kết mà không cần tạo bất kỳ CoreValue hoặc Người dùng mới nào

Cho # 1, tôi có điều này để hoạt động:

User.find(current_user.id).core_values.create({:value => v, :created_by => current_user.id}) 

Điều này tạo ra một CoreValue mới với: giá trị và: created_by và tạo liên kết.

Đối với # 2, tôi đã thử một vài điều, nhưng dường như không thể tạo ra liên kết CHỈ.

Cảm ơn sự giúp đỡ của bạn!

Trả lời

21

Bạn có thể thực hiện việc này theo quy trình hai bước, sử dụng phương pháp find_or_create rất hữu ích. find_or_create trước tiên sẽ cố gắng tìm một bản ghi và nếu nó không tồn tại, hãy tạo nó. Một cái gì đó như thế này nên làm như lừa:

core_value = CoreValue.find_or_create_by_value(v, :created_by => current_user.id) 
current_user.core_values << core_value 

Một số lưu ý:

  • Dòng đầu tiên sẽ tìm hoặc tạo ra giá trị v. Nếu nó không tồn tại và được tạo ra, nó sẽ đặt created_by thành current_user.id.
  • Không cần phải làm User.find(current_user.id), vì điều đó sẽ trả lại cùng một đối tượng là current_user.
  • current_user.core_values là một mảng và bạn có thể dễ dàng thêm một giá trị khác vào mảng đó bằng cách sử dụng <<.

Để ngắn gọn, sau đây sẽ được giống như ví dụ mã trên:

current_user.core_values << CoreValue.find_or_create_by_value(v, :created_by => current_user.id) 
+0

Cảm ơn! Không biết core_values ​​là một mảng - và chắc chắn không biết thêm vào mảng sẽ tạo ra một INSERT. Ngọt! Bất kỳ cách nào để chỉ tạo liên kết nếu bản ghi không tồn tại? Tôi sẽ xem xét các phương pháp mảng, tôi đoán vậy? Có lẽ current_user.core_values.include? – jmccartie

+0

@jmccartie Đó có thể là một cách để làm điều đó, vâng. Để làm rõ, tôi cảm thấy tôi nên thêm rằng 'core_values' không phải là * luôn luôn * một mảng - như bạn đã biết, bạn có thể gọi' core_values.create' mà không phải là một phương thức mảng hợp lệ. Một định nghĩa tốt hơn sẽ là nó "hoạt động như một mảng." – vonconrad

+0

cảm ơn bạn đã theo dõi. bao gồm? sẽ không hoạt động. cố gắng tìm ra nếu tôi có thể tìm thấy id core_value mới bên trong current_user.core_values ​​... hmmmm – jmccartie

4

Thêm một phương pháp trong mô hình người dùng của bạn:

class User < ActiveRecord::Base 
    def assign_core_value(v) 
    core_values.find_by_name(v) || (self.core_values << 
     CoreValue.find_or_create_by_name(:name => v, :created_by => self)).last 
    end 
end 

Phương pháp assign_core_value đáp ứng yêu cầu 1, 2 và trả về giá trị cốt lõi được gán cho người dùng (với tên đã cho).

Bây giờ bạn có thể làm như sau:

current_user.assign_core_value(v) 

Note 1

Phương pháp logic là như sau:

1) Kiểm tra nếu các CoreValue đã được gắn liền với người dùng. Nếu không có hành động nào được thực hiện, giá trị cốt lõi sẽ được trả về.

2) Kiểm tra xem CoreValue có tên đã tồn tại chưa. Nếu không tạo ra CoreValue. Liên kết giá trị cốt lõi (được tạo/tìm thấy) với người dùng.

+0

Cảm ơn! Ý tưởng tốt để thêm điều này vào mô hình người dùng. Điều này sẽ tạo ra liên kết nếu nó đã tồn tại? – jmccartie

+0

Cập nhật câu trả lời của tôi với một số lời giải thích. Hãy xem. –

0

Bản ghi đang hoạt động đã cung cấp cho bạn phương thức. Trong trường hợp của bạn,

val = CoreValue.find_by_value(v) 
current_user.core_values << val 

Bạn cũng có thể chuyển một số đối tượng theo cách này theo cách này. Tất cả các liên kết sẽ được tạo

Kiểm tra this để biết thêm thông tin

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