Cách tốt nhất để tạo cơ sở dữ liệu trong Rails là gì?


82

Tôi có một nhiệm vụ rake điền một số dữ liệu ban đầu trong ứng dụng rails của tôi. Ví dụ: quốc gia, tiểu bang, nhà cung cấp dịch vụ di động, v.v.

Theo cách tôi thiết lập nó bây giờ, là tôi có một loạt các câu lệnh tạo trong các tệp trong / db / fixtures và một tác vụ rake xử lý chúng. Ví dụ, một mô hình tôi có là chủ đề. Tôi có một tệp theme.rb trong / db / fixtures trông giống như sau:

Theme.delete_all
Theme.create(:id => 1, :name=>'Lite', :background_color=>'0xC7FFD5', :title_text_color=>'0x222222',
                      :component_theme_color=>'0x001277', :carrier_select_color=>'0x7683FF', :label_text_color=>'0x000000',
                      :join_upper_gradient=>'0x6FAEFF', :join_lower_gradient=>'0x000000', :join_text_color=>'0xFFFFFF',
                      :cancel_link_color=>'0x001277', :border_color=>'0x888888', :carrier_text_color=>'0x000000', :public => true)

Theme.create(:id => 2, :name=>'Metallic', :background_color=>'0x000000', :title_text_color=>'0x7299FF',
                      :component_theme_color=>'0xDBF2FF', :carrier_select_color=>'0x000000', :label_text_color=>'0xDBF2FF',
                      :join_upper_gradient=>'0x2B25FF', :join_lower_gradient=>'0xBEFFAC', :join_text_color=>'0x000000',
                      :cancel_link_color=>'0xFF7C12', :border_color=>'0x000000', :carrier_text_color=>'0x000000', :public => true)

Theme.create(:id => 3, :name=>'Blues', :background_color=>'0x0060EC', :title_text_color=>'0x000374',
                      :component_theme_color=>'0x000374', :carrier_select_color=>'0x4357FF', :label_text_color=>'0x000000',
                      :join_upper_gradient=>'0x4357FF', :join_lower_gradient=>'0xffffff', :join_text_color=>'0x000000',
                      :cancel_link_color=>'0xffffff', :border_color=>'0x666666', :carrier_text_color=>'0x000000', :public => true)
puts "Success: Theme data loaded"

Ý tưởng ở đây là tôi muốn cài đặt một số chủ đề cổ phiếu cho người dùng bắt đầu. Tôi có một vấn đề với phương pháp này.

Đặt ID không hoạt động. Điều này có nghĩa là nếu tôi quyết định thêm một chủ đề, hãy gọi nó là 'Red', sau đó tôi chỉ muốn thêm câu lệnh chủ đề vào tệp cố định này và gọi tác vụ rake để gửi lại cơ sở dữ liệu. Nếu tôi làm điều đó, bởi vì các chủ đề thuộc về các đối tượng khác và id của chúng thay đổi khi khởi tạo lại này, tất cả các liên kết đều bị hỏng.

Câu hỏi của tôi trước hết là, đây có phải là một cách tốt để xử lý việc seeding một cơ sở dữ liệu không? Trong một bài viết trước, điều này đã được đề xuất cho tôi.

Nếu vậy, làm cách nào để tôi có thể mã hóa cứng các ID, và có bất kỳ nhược điểm nào của điều đó không?

Nếu không, cách tốt nhất để bắt đầu cơ sở dữ liệu là gì?

Tôi sẽ thực sự đánh giá cao các câu trả lời dài và được suy nghĩ kết hợp các phương pháp hay nhất.

Câu trả lời:


113

Đang cập nhật vì những câu trả lời này hơi lỗi thời (mặc dù một số vẫn được áp dụng).

Tính năng đơn giản được thêm vào trong rails 2.3.4, db / seed.rb

Cung cấp một nhiệm vụ cào mới

rake db:seed

Tốt cho việc điền các bản ghi tĩnh phổ biến như tiểu bang, quốc gia, v.v.

http://railscasts.com/episodes/179-seed-data

* Lưu ý rằng bạn có thể sử dụng các đồ đạc nếu bạn đã tạo chúng để điền vào tác vụ db: seed bằng cách đưa phần sau vào tệp seed.rb của bạn (từ tập railscast):

require 'active_record/fixtures'
Fixtures.create_fixtures("#{Rails.root}/test/fixtures", "operating_systems")

Đối với Rails 3.x, hãy sử dụng 'ActiveRecord :: Fixtures' thay vì hằng số 'Fixtures'

require 'active_record/fixtures'
ActiveRecord::Fixtures.create_fixtures("#{Rails.root}/test/fixtures", "fixtures_file_name")

28

Thông thường có 2 loại dữ liệu hạt giống được yêu cầu.

  • Dữ liệu cơ bản mà cốt lõi của ứng dụng của bạn có thể dựa vào. Tôi gọi đây là hạt giống thông thường.
  • Dữ liệu môi trường , chẳng hạn như để phát triển ứng dụng, rất hữu ích khi có một loạt dữ liệu ở trạng thái đã biết mà chúng ta có thể sử dụng để làm việc trên ứng dụng cục bộ (câu trả lời của Factory Girl ở trên bao gồm loại dữ liệu này).

Theo kinh nghiệm của tôi, tôi luôn bắt gặp sự cần thiết của hai loại dữ liệu này. Vì vậy, tôi kết hợp một viên ngọc nhỏ để mở rộng hạt giống của Rails và cho phép bạn thêm nhiều tệp hạt giống chung trong db / seed / và bất kỳ dữ liệu hạt giống môi trường nào trong db / seed / ENV, ví dụ như db / seed / development.

Tôi nhận thấy cách tiếp cận này đủ để cung cấp cho dữ liệu hạt giống của tôi một số cấu trúc và cho tôi sức mạnh để thiết lập môi trường phát triển hoặc môi trường tổ chức của tôi ở một trạng thái đã biết chỉ bằng cách chạy:

rake db:setup

Đồ đạc dễ vỡ và bong tróc để bảo trì, cũng như bãi rác sql thông thường.


Tôi thích các thuật ngữ "dữ liệu hệ thống" và "dữ liệu thời gian chạy" để mô tả những thứ mà mã dựa trên dữ liệu hiện có so với dữ liệu từ người dùng. Đôi khi ranh giới giữa chúng bị mờ.
Tim Abell

27

Factory_bot có vẻ như nó sẽ làm được những gì bạn đang cố gắng đạt được. Bạn có thể xác định tất cả các thuộc tính chung trong định nghĩa mặc định và sau đó ghi đè chúng tại thời điểm tạo. Bạn cũng có thể chuyển một id cho nhà máy:

Factory.define :theme do |t|
  t.background_color '0x000000'
  t.title_text_color '0x000000',
  t.component_theme_color '0x000000'
  t.carrier_select_color '0x000000'
  t.label_text_color '0x000000',
  t.join_upper_gradient '0x000000'
  t.join_lower_gradient '0x000000'
  t.join_text_color '0x000000',
  t.cancel_link_color '0x000000'
  t.border_color '0x000000'
  t.carrier_text_color '0x000000'
  t.public true
end

Factory(:theme, :id => 1, :name => "Lite", :background_color => '0xC7FFD5')
Factory(:theme, :id => 2, :name => "Metallic", :background_color => '0xC7FFD5')
Factory(:theme, :id => 3, :name => "Blues", :background_color => '0x0060EC')

Khi được sử dụng với faker, nó có thể điền vào cơ sở dữ liệu một cách thực sự nhanh chóng với các liên kết mà không cần phải làm phiền với Fixtures (yuck).

Tôi có mã như thế này trong một nhiệm vụ cào.

100.times do
    Factory(:company, :address => Factory(:address), :employees => [Factory(:employee)])
end

11
FactoryGirl thực sự được dùng để thử nghiệm thay cho đồ đạc, nhưng nó cũng có thể được sử dụng để tải các thứ vào sản xuất. Sử dụng tác vụ rake có db: migrate làm điều kiện tiên quyết để tải tất cả dữ liệu mặc định. Bạn có thể cần phải làm cho tác vụ rake đủ thông minh để nó không tạo ra các bản sao của dữ liệu hiện có.
Bob Aman

2
Sử dụng FactoryGirl cho hạt giống không được khuyến khích, hãy xem bài đăng này .
blackbiron

26

Sử dụng seeds.rbtệp hoặc FactoryBotlà tuyệt vời, nhưng chúng tương ứng là tuyệt vời cho cấu trúc dữ liệu cố định và thử nghiệm.

Các seedbankđá quý có thể cung cấp cho bạn kiểm soát nhiều hơn và mô đun để hạt giống của bạn. Nó chèn các nhiệm vụ cào và bạn cũng có thể xác định sự phụ thuộc giữa các hạt giống của mình. Danh sách nhiệm vụ cào của bạn sẽ có những bổ sung sau (ví dụ):

rake db:seed                    # Load the seed data from db/seeds.rb, db/seeds/*.seeds.rb and db/seeds/ENVIRONMENT/*.seeds.rb. ENVIRONMENT is the current environment in Rails.env.
rake db:seed:bar                # Load the seed data from db/seeds/bar.seeds.rb
rake db:seed:common             # Load the seed data from db/seeds.rb and db/seeds/*.seeds.rb.
rake db:seed:development        # Load the seed data from db/seeds.rb, db/seeds/*.seeds.rb and db/seeds/development/*.seeds.rb.
rake db:seed:development:users  # Load the seed data from db/seeds/development/users.seeds.rb
rake db:seed:foo                # Load the seed data from db/seeds/foo.seeds.rb
rake db:seed:original           # Load the seed data from db/seeds.rb

1

Rails có một cách được xây dựng để gieo dữ liệu như được giải thích ở đây .

Một cách khác là sử dụng một viên ngọc để gieo hạt cao cấp hơn hoặc dễ dàng hơn như: ngân hàng hạt giống .

Ưu điểm chính của gem này và lý do tôi sử dụng nó là nó có các khả năng nâng cao như các phụ thuộc tải dữ liệu và dữ liệu hạt giống trên mỗi môi trường.

Thêm một câu trả lời cập nhật vì câu trả lời này lần đầu tiên xuất hiện trên google.


-3

Cách tốt nhất là sử dụng đồ đạc.

Lưu ý: Hãy nhớ rằng đồ đạc thực hiện chèn trực tiếp và không sử dụng mô hình của bạn, vì vậy nếu bạn có lệnh gọi lại điền dữ liệu, bạn sẽ cần tìm cách giải quyết.


-4

Thêm nó trong di chuyển cơ sở dữ liệu, theo cách đó mọi người sẽ nhận được nó khi họ cập nhật. Xử lý tất cả logic của bạn trong mã ruby ​​/ rails, vì vậy bạn không bao giờ phải gặp rắc rối với cài đặt ID rõ ràng.


nếu tôi cần thay đổi dữ liệu ban đầu, mọi thứ có thể trở nên lộn xộn khi sử dụng di chuyển. nhận xét thứ hai của bạn không thực sự có ý nghĩa. liên kết thông qua khóa ngoại sẽ bị phá hủy
Tony

c = Category.create (thứ) p = Post.create (thứ) p.category = c Không cần đặt ID một cách rõ ràng. Nếu bạn thay đổi dữ liệu ban đầu, bạn chỉ cần tạo một di chuyển mới. Khá dễ.
Matt Rogish

giả sử các liên kết có thể được thực hiện tại thời điểm đối tượng được tạo. đây là một ví dụ mà tôi tin rằng logic của bạn không thành công ... hãy sửa cho tôi nếu tôi sai. tôi gieo hạt DB với các chủ đề mẫu. user id = 1 tạo id mẫu = 2 và với id chủ đề = 4. tại thời điểm này, một bản ghi nằm trong db như sau: template: id = 2, user_id = 1, theme_id = 4. bây giờ nếu tôi tái init db, chủ đề id = 4 tại là theme id = 10 ... và sau đó mẫu của người dùng được theo chủ đề không đúng cách
Tony

tốt, nó phụ thuộc vào ý của bạn khi "re-init" - nếu bạn bắt đầu từ 0, Rails sẽ tự động xử lý tất cả các liên kết. Nếu bạn khó mã hóa giá trị ID (xấu !!!), thì có, nó sẽ nổ tung.
Matt Rogish

Được rồi, tôi bắt đầu thấy quan điểm của bạn, nhưng tôi phải chạy kịch bản này bởi bạn. tôi gieo vào cơ sở dữ liệu với một bảng tra cứu quốc gia. Hoa Kỳ => quốc gia id = 1. sau đó người dùng tạo một nhà hàng tồn tại ở Hoa Kỳ. hàng cơ sở dữ liệu nhà hàng có country_id = 1. điều này rất phổ biến, phải không? Tôi quyết định sau đó rằng tôi muốn thêm nhiều quốc gia hơn ... nếu tôi xóa sạch db và lập lại bảng tra cứu quốc gia, bây giờ quốc gia nhà hàng không còn chính xác nữa trừ khi id giống nhau. làm thế nào để tôi xử lý điều này?
Tony
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.