Tôi đã tìm thấy câu trả lời "SQL thuần túy" cho câu hỏi này. Có cách nào không, trong Rails, để đặt lại trường id cho một bảng cụ thể?
Tại sao tôi muốn làm điều này? Bởi vì tôi có các bảng với dữ liệu liên tục di chuyển - hiếm khi có hơn 100 hàng, nhưng luôn khác nhau. Bây giờ nó lên đến 25k, và không có điểm nào trong đó. Tôi có ý định sử dụng một trình lên lịch nội bộ cho ứng dụng Rails (rufus-scheduler) để chạy trường id reset hàng tháng hoặc lâu hơn.Đường ray để đặt lại hạt giống trên trường id
Trả lời
Tôi đã đưa ra giải pháp dựa trên câu trả lời của hgimenez và this other one.
Vì tôi thường làm việc với Sqlite hoặc PostgreSQL, tôi chỉ phát triển cho những người đó; nhưng mở rộng nó ra, nói MySQL, không nên quá phiền hà.
Đặt này bên trong lib/và yêu cầu nó trên một initializer:
# lib/active_record/add_reset_pk_sequence_to_base.rb
module ActiveRecord
class Base
def self.reset_pk_sequence
case ActiveRecord::Base.connection.adapter_name
when 'SQLite'
new_max = maximum(primary_key) || 0
update_seq_sql = "update sqlite_sequence set seq = #{new_max} where name = '#{table_name}';"
ActiveRecord::Base.connection.execute(update_seq_sql)
when 'PostgreSQL'
ActiveRecord::Base.connection.reset_pk_sequence!(table_name)
else
raise "Task not implemented for this DB adapter"
end
end
end
end
Cách sử dụng:
Client.count # 10
Client.destroy_all
Client.reset_pk_sequence
Client.create(:name => 'Peter') # this client will have id=1
EDIT: Kể từ khi trường hợp thông thường nhất mà bạn sẽ muốn làm điều này là sau khi thanh toán bù trừ một bảng cơ sở dữ liệu, tôi khuyên bạn nên xem xét database_cleaner. Nó xử lý ID đặt lại tự động. Bạn có thể nói với nó để xóa bảng vừa chọn như thế này:
DatabaseCleaner.clean_with(:truncation, :only => %w[clients employees])
Nếu bạn mới sử dụng Rails như tôi, [bài đăng trên blog này] (http://blog.chrisblunt.com/rails-3-how-to-autoload-and-autorequire-your-custom -library-code /) đã giúp tôi thiết lập mã này trong trình khởi tạo. –
Một vấn đề là các loại lĩnh vực được thực hiện khác nhau cho chuỗi databases- khác nhau, tính năng tự động gia tăng, vv
Bạn luôn có thể thả và tái thêm bàn.
Không có điều gì trong Rails. Nếu bạn cần một id tốt đẹp để hiển thị người dùng sau đó lưu trữ chúng trong một bảng riêng biệt và tái sử dụng chúng.
Đó là thông minh! Tôi không hiển thị nó cho người dùng mặc dù. Tôi chỉ muốn tránh tràn ngập trong 10.000 năm. :-) – Trevoke
Bạn chỉ có thể thực hiện điều này trong đường ray nếu _ids đang được đặt bằng đường ray. Miễn là các _ids đang được thiết lập bởi cơ sở dữ liệu của bạn, bạn sẽ không thể kiểm soát chúng mà không cần sử dụng SQL.
Lưu ý phụ: Tôi đoán sử dụng đường ray để thường xuyên gọi thủ tục SQL để đặt lại hoặc giảm và tạo lại chuỗi sẽ không phải là giải pháp hoàn toàn SQL, nhưng tôi không nghĩ đó là những gì bạn đang yêu cầu ...
EDIT:
Tuyên bố từ chối trách nhiệm: Tôi không biết nhiều về đường ray.
Từ góc nhìn SQL, nếu bạn có một bảng với các cột id first_name last_name
và bạn thường insert into table (first_name, last_name) values ('bob', 'smith')
bạn chỉ có thể thay đổi các truy vấn của bạn để insert into table (id, first_name, last_name) values ([variable set by rails], 'bob', 'smith')
Bằng cách này, _id được thiết lập bởi một biến, thay vì được tự động thiết lập bởi SQL. Tại thời điểm đó, đường ray có toàn quyền kiểm soát những gì các _ids (mặc dù nếu nó là một PK bạn cần phải chắc chắn rằng bạn không sử dụng cùng một giá trị trong khi nó vẫn còn ở đó).
Nếu bạn đang đi để lại sự phân công lên đến cơ sở dữ liệu, bạn phải có đường ray chạy (trên bất cứ thời gian lịch trình) một cái gì đó như:
DROP SEQUENCE MY_SEQ;
CREATE SEQUENCE MY_SEQ START WITH 1 INCREMENT BY 1 MINVALUE 1;
để bất cứ điều gì tự kiểm soát ids cho bảng của bạn. Điều này sẽ loại bỏ chuỗi hiện tại và tạo chuỗi mới. Đây là cách đơn giản nhất mà tôi biết về việc bạn 'đặt lại' một chuỗi.
Vâng, tôi sẽ phải sử dụng Rails để thường xuyên gọi một câu lệnh SQL để tái hạt giống, tôi nghĩ :) Ngoài sự tò mò, làm cách nào để Rails đặt _id? – Trevoke
Bạn chưa bao giờ đề cập đến DBMS bạn đang sử dụng. Nếu đây là PostgreSQL, các ActiveRecord postgres bộ chuyển đổi có một phương pháp reset_pk_sequences!
mà bạn có thể sử dụng:
ActiveRecord::Base.connection.reset_pk_sequence!('table_name')
Cảm ơn, Harold. Điều này là tiết kiệm ass của tôi ngay bây giờ. –
Thứ tốt Harold! – RubyFanatic
Tên bảng có thể được tăng bởi Rails với 'Class.table_name', có thể làm cho nó trở nên đẹp hơn. Cảm ơn! –
Tôi giả sử bạn không quan tâm đến dữ liệu:
def self.truncate!
connection.execute("truncate table #{quoted_table_name}")
end
Hoặc nếu bạn làm thế, nhưng không phải quá nhiều (có một lát thời gian mà dữ liệu chỉ tồn tại trong bộ nhớ):
def self.truncate_preserving_data!
data = all.map(&:clone).each{|r| raise "Record would not be able to be saved" unless r.valid? }
connection.execute("truncate table #{quoted_table_name}")
data.each(&:save)
end
này sẽ cung cấp hồ sơ mới, với các thuộc tính như nhau, nhưng id bắt đầu từ 1.
Bất cứ điều gì belongs_to
trong bảng này có thể trở nên khó khăn.
Đó là một câu trả lời gọn gàng, nhưng cắt ngắn không phải là một lựa chọn cho tôi. Tôi đã học được điều gì đó mặc dù :) – Trevoke
Dựa trên @hgmnz 's câu trả lời, tôi đã thực hiện phương pháp này sẽ thiết lập các chuỗi với bất kỳ giá trị mà bạn thích ... (Chỉ thử nghiệm với Postgres bộ chuyển đổi.)
# change the database sequence to force the next record to have a given id
def set_next_id table_name, next_id
connection = ActiveRecord::Base.connection
def connection.set_next_id table, next_id
pk, sequence = pk_and_sequence_for(table)
quoted_sequence = quote_table_name(sequence)
select_value <<-end_sql, 'SCHEMA'
SELECT setval('#{quoted_sequence}', #{next_id}, false)
end_sql
end
connection.set_next_id(table_name, next_id)
end
Điều này hoạt động ra khỏi hộp ... cảm ơn bạn! – ChaosFreak
Đường ray cho ví dụ MySQL, nhưng với mất tất cả dữ liệu trong bảng users
:
ActiveRecord::Base.connection.execute('TRUNCATE TABLE users;')
Có lẽ sẽ giúp người;)
Đây là câu trả lời giống như https://stackoverflow.com/a/2098639/234025. – Trevoke
- 1. Đường ray - Kết hợp hạt giống HABTM
- 2. Đường ray: trường id là 0 khi gọi Model.new
- 3. Cách thêm dữ liệu hạt giống mới vào cơ sở dữ liệu đường ray hiện có
- 4. Toán tử giống như trong ruby trên đường ray
- 5. Đường ray: cách ID hoặc Tên được đặt trong text_field_tag?
- 6. Gửi hạt giống/Đặt hạt/C trong mã R
- 7. Đặt tăng hạt giống :: ngẫu nhiên
- 8. đường ray 3 tìm hoặc tạo dựa trên nhiều trường
- 9. Đường ray Nhận nhiều theo ID
- 10. Trường hợp nên quản lý cuộc gọi lại được đặt trong ứng dụng đường ray?
- 11. đường ray đến id cụ thể
- 12. Chia hạt giống thành nhiều phần?
- 13. Đường ray nested_form đặt hàng
- 14. Cách đánh dấu trường trên lỗi xác thực đường ray
- 15. làm thế nào để lấy ID lại từ một URL bằng đường ray
- 16. Chạy rake db: hạt giống không tải từ hạt giống.rb
- 17. Nạp lại đường ray initializers
- 18. Asset và @ font-face trên đường ray (đường ray 3.2.3)
- 19. Đường ray: Đặt thuộc tính trong after_create
- 20. Đường ray Tuyến đường dựa trên một cái gì đó khác với ID
- 21. Cách kiểm tra môi trường đường ray?
- 22. Giống và sử dụng lại các hạt giống ngẫu nhiên của Python
- 23. Cách thêm id html vào thẻ form_for trong đường ray?
- 24. Tuyến đường ray: GET mà không có thông số: id
- 25. Số nguyên trong khi đặt hạt giống là gì?
- 26. Đặt cấu hình Notepad ++ cho ruby trên đường ray
- 27. Đường ray - Thêm trường tùy chỉnh khi chạy trong ActiveRecord
- 28. Trường ẩn trong đường ray dạng
- 29. Đường ray - Tìm theo với 2 trường?
- 30. đặt hằng số cấu hình tùy thuộc vào môi trường trong đường ray
Tôi ghét nó khi người ta nói điều này, nhưng các ý kiến là đúng ... có thực sự không có cách nào để làm điều này trong đường ray, và, to và lớn, nó không cần thiết phải làm gì cả. Nếu bạn chỉ tránh nhận được số lượng lớn bởi vì bạn muốn hiển thị nó cho người dùng, bạn chỉ nên có một cột PID, và sử dụng nó cho màn hình của bạn. – aronchick
Và làm thế nào tôi sẽ đi về việc tạo ra một cột PID? Đó có phải là điều tương tự như Jonas đã gợi ý bên dưới trong câu trả lời của anh ta không? – Trevoke