2012-10-03 25 views
10

Tôi có mô hình Đánh giá. Đánh giá có nhiều điểm. Bất cứ khi nào một đánh giá mới được tạo ra, một bản ghi điểm được tạo ra cho mỗi người dùng cần đánh giá (xem dưới đây cho phương pháp hiện tại tôi đang sử dụng để làm điều này.) Vì vậy, ví dụ, 40 hồ sơ điểm có thể được tạo ra cùng một lúc. Chủ sở hữu Đánh giá sau đó cập nhật từng bản ghi điểm với điểm số của Người dùng.Đường ray 3, câu lệnh chèn SQL nguyên bản tùy chỉnh

Tôi đang tìm cách sử dụng SQL thô vì mỗi lần chèn là giao dịch của riêng nó và chậm.

Tôi muốn chuyển đổi sau đây vào một tuyên bố chèn khối lượng sử dụng SQL liệu:

def build_evaluation_score_items 
    self.job.active_employees.each do |employee| 
    employee_score = self.scores.build 
    employee_score.user_id = employee.id 
    employee_score.save 
    end 
end 

Bất kỳ suy nghĩ về cách thức này có thể được thực hiện? Tôi đã cố gắng thích ứng với một mẫu mã từ trang web Coffee Powered của Chris Heald nhưng không có súc sắc.

Nhờ bất kỳ ai sẵn sàng trợ giúp!

CHỈNH SỬA 1

Tôi bỏ qua đề cập đến phương pháp hiện tại được gói trong giao dịch. Vì vậy, về cơ bản, tôi đang cố gắng để thêm này vào khối mã để tất cả mọi thứ được chèn vào trong một tuyên bố (** Đoạn mã này là từ trang web Coffee Powered của Chris Heald đã thảo luận về chủ đề này. bài này là> 3 tuổi):.

inserts = [] 
TIMES.times do 
    inserts.push "(3.0, '2009-01-23 20:21:13', 2, 1)" 
end 
sql = "INSERT INTO user_node_scores (`score`, `updated_at`, `node_id`, `user_id`)VALUES #{inserts.join(", ")}" 

tôi muốn được hạnh phúc để hiển thị các mã từ một số nỗ lực của tôi không làm việc ...

Cảm ơn một lần nữa!

Vâng, tôi đã gom góp một cái gì đó tương tự như đoạn mã trên nhưng tôi nhận được một lỗi không hợp lệ câu lệnh SQL xung quanh (phần 'evaluation_id'. Bất kỳ suy nghĩ?

def build_evaluation_score_items 
    inserts = [] 
    self.job.active_employees.each do |employee| 
    inserts.push "(#{self.id}, #{employee.id}, #{Time.now}, #{Time.now})" 
    end 
    sql = "INSERT INTO scores ('evaluation_id', `user_id`, 'created_at', `updated_at`)VALUES #{inserts.join(", ")}" 
    ActiveRecord::Base.connection.execute(sql) 
end 

Bất kỳ ý tưởng như những gì trong ? trên SQL code đang gây ra lỗi

+1

phần created_at không làm việc cho tôi kể từ khi nó đang tạo ra một chuỗi Postgres là không phân tích cú pháp. 'ActiveRecord :: StatementInvalid: PG :: Cú phápError: ERROR: lỗi cú pháp tại hoặc gần" 07 " LINE 4: (1, 1, 100, 2017-02-20 07:00:56 +0000, 2017-02-20 07 ... ' – Gambo

Trả lời

17

Vâng, sau nhiều lần thử và lỗi, đây là câu trả lời cuối cùng. Điều thú vị là tất cả các bản ghi được chèn qua một câu lệnh. Tất nhiên, xác nhận bị bỏ qua (vì vậy điều này sẽ không phù hợp nếu bạn yêu cầu xác thực mô hình khi tạo) nhưng trong trường hợp của tôi, điều đó không cần thiết vì tất cả những gì tôi đang làm là thiết lập hồ sơ điểm cho đánh giá của từng nhân viên. Tất nhiên, các xác nhận hợp lệ hoạt động như mong đợi khi người lãnh đạo công việc cập nhật điểm đánh giá của nhân viên.

def build_evaluation_score_items 
    inserts = [] 
    time = Time.now.to_s(:db) 
    self.job.active_employees.each do |employee| 
    inserts.push "(#{self.id}, #{employee.id}, '#{time}')" 
    end 
    sql = "INSERT INTO scores (evaluation_id, user_id, created_at) VALUES #{inserts.join(", ")}" 
    ActiveRecord::Base.connection.execute(sql) 
end 
+0

Tôi đã sử dụng bạn r giải pháp để đặt cùng một cái gì đó cho các nhu cầu của riêng tôi. Tôi đã thực hiện một số thử nghiệm hiệu suất và cần phải điền vào DB với nhiều dữ liệu ngẫu nhiên (hàng triệu hàng) * một cách nhanh chóng * (tức là không sử dụng ActiveRecord). – user664833

+1

Điều này không hiệu quả đối với tôi vì 'thời gian' có đầu ra sai. Postgres đang ném điều này: 'ActiveRecord :: StatementInvalid: PG :: Cú phápError: ERROR: lỗi cú pháp tại hoặc gần" 07 " LINE 4: (1, 1, 100, 2017-02-20 07:04:11, 2017- 02-20 07:04:11 ... ' – Gambo

+0

Sử dụng chèn để xóa bộ nhớ cache. – MRifat

5

tôi nghĩ rằng những gì bạn đang tìm kiếm là:

def build_evaluation_score_items 
    ActiveRecord::Base.transaction do 
    self.job.active_employees.each do |employee| 
     employee_score = self.scores.build 
     employee_score.user_id = employee.id 
     employee_score.save 
    end 
    end 
end 

Mọi giao dịch con tự động "đẩy" lên đến tran mẹ saction. Điều này sẽ ngăn chặn chi phí của quá nhiều giao dịch và tăng hiệu suất.

Bạn có thể đọc thêm về các giao dịch ActiveRecord here.

CẬP NHẬT

Xin lỗi, tôi hiểu lầm. Giữ câu trả lời ở trên cho hậu thế. Hãy thử điều này:

def build_evaluation_score_items 
    raw_sql = "INSERT INTO your_table ('user_id', 'something_else') VALUES " 
    insert_values = "('%s', '%s')," 
    self.job.active_employees.each do |employee| 
    raw_sql += insert_values % employee.id, "something else" 
    end 
    ActiveRecord::Base.connection.execute raw_sql 
end 
+0

Cảm ơn gợi ý Tôi bỏ qua để chỉ ra trong bài viết của tôi rằng tôi hiện đang có tuyên bố gói trong một giao dịch trong mã nhưng đó vẫn còn tối ưu, vì nó vẫn thực thi các câu lệnh chèn cho mỗi nhân viên. Lợi ích duy nhất của giao dịch là chỉ số db không được cập nhật –

+0

Tôi đã cập nhật câu trả lời của mình với một giải pháp tiềm năng.Xin vui lòng cho tôi biết nếu nó giúp bạn –

+0

Xin chào Chuck - Tôi đồng ý với việc giữ mục đầu tiên ở đó Điều đó nói rằng, thật không may, tôi nhận được lỗi sau: phương thức undefined 'execute 'cho ActiveRecord :: Base: Class.Tôi sẽ tìm hiểu về lệnh thi hành thích hợp và sẽ báo cáo lại. –

6

Thay vì tạo SQL trực tiếp (và tự mở SQL injection và các vấn đề khác), tôi khuyên bạn nên activerecord-import gem. Nó có thể phát hành các lệnh INSERT nhiều hàng, cùng với các chiến lược khác.

Sau đó, bạn có thể viết một cái gì đó như:

def build_evaluation_score_items 
    new_scores = job.active_employees.map do |employee| 
    scores.build(:user_id => employee.id) 
    end 
    Score.import new_scores 
end 
Các vấn đề liên quan