|
1 | 1 | # db/seeds.rb |
2 | 2 |
|
3 | 3 | # ====== Create Puzzle records ====== |
| 4 | +# Archived entries carry `sent_at` and a fixed `success_rate` (% of 10 users |
| 5 | +# who answer correctly). Rates <= 80 appear in the "low success rate" filter; |
| 6 | +# rates > 80 do not. Entries without `state` default to :pending. |
4 | 7 | puzzles = [ |
5 | 8 | { |
6 | 9 | question: "Ruby or Rails provided this method? Array.new(5) { |i| i * 2 }", |
|
26 | 29 | question: "Ruby or Rails provided this method? params[:id]", |
27 | 30 | answer: :rails, |
28 | 31 | explanation: "`params[:id]` is used in Rails to fetch query parameters or URL parameters in controller actions." |
| 32 | + }, |
| 33 | + { |
| 34 | + question: "Ruby or Rails provided this method? before_action :authenticate_user!", |
| 35 | + answer: :rails, |
| 36 | + explanation: "`before_action` is a Rails callback defined in `ActionController::Callbacks`. It runs specified methods before controller actions.", |
| 37 | + state: :archived, |
| 38 | + sent_at: 7.days.ago, |
| 39 | + success_rate: 20 |
| 40 | + }, |
| 41 | + { |
| 42 | + question: "Ruby or Rails provided this method? 42.times { puts 'hello' }", |
| 43 | + answer: :ruby, |
| 44 | + explanation: "`Integer#times` is a core Ruby method that iterates a block a specified number of times.", |
| 45 | + state: :archived, |
| 46 | + sent_at: 6.days.ago, |
| 47 | + success_rate: 40 |
| 48 | + }, |
| 49 | + { |
| 50 | + question: "Ruby or Rails provided this method? User.where(active: true).order(:name)", |
| 51 | + answer: :rails, |
| 52 | + explanation: "`where` and `order` are ActiveRecord query methods provided by Rails to build SQL queries.", |
| 53 | + state: :archived, |
| 54 | + sent_at: 5.days.ago, |
| 55 | + success_rate: 50 |
| 56 | + }, |
| 57 | + { |
| 58 | + question: "Ruby or Rails provided this method? 'hello world'.split(' ')", |
| 59 | + answer: :ruby, |
| 60 | + explanation: "`String#split` is a core Ruby method that divides a string into an array based on a delimiter.", |
| 61 | + state: :archived, |
| 62 | + sent_at: 4.days.ago, |
| 63 | + success_rate: 70 |
| 64 | + }, |
| 65 | + { |
| 66 | + question: "Ruby or Rails provided this method? flash[:notice] = 'Saved!'", |
| 67 | + answer: :rails, |
| 68 | + explanation: "`flash` is a Rails feature provided by `ActionDispatch::Flash` for passing messages between requests.", |
| 69 | + state: :archived, |
| 70 | + sent_at: 3.days.ago, |
| 71 | + success_rate: 80 |
| 72 | + }, |
| 73 | + { |
| 74 | + question: "Ruby or Rails provided this method? [1, 2, 3].reduce(:+)", |
| 75 | + answer: :ruby, |
| 76 | + explanation: "`Enumerable#reduce` (also `inject`) is a core Ruby method that combines elements using a binary operation.", |
| 77 | + state: :archived, |
| 78 | + sent_at: 2.days.ago, |
| 79 | + success_rate: 90 |
| 80 | + }, |
| 81 | + { |
| 82 | + question: "Ruby or Rails provided this method? validates :email, presence: true, uniqueness: true", |
| 83 | + answer: :rails, |
| 84 | + explanation: "`validates` is an ActiveModel/ActiveRecord method from Rails that adds validation rules to models.", |
| 85 | + state: :archived, |
| 86 | + sent_at: 1.day.ago, |
| 87 | + success_rate: 100 |
29 | 88 | } |
30 | 89 | ] |
31 | 90 |
|
| 91 | +success_rate_by_question = puzzles.each_with_object({}) do |p, h| |
| 92 | + h[p[:question]] = p[:success_rate] if p[:success_rate] |
| 93 | +end |
| 94 | + |
32 | 95 | puzzles.each do |p| |
33 | 96 | Puzzle.find_or_create_by!(question: p[:question]) do |puzzle| |
34 | 97 | puzzle.answer = p[:answer] |
35 | 98 | puzzle.explanation = p[:explanation] |
| 99 | + puzzle.state = p[:state] if p[:state] |
| 100 | + puzzle.sent_at = p[:sent_at] |
36 | 101 | end |
37 | 102 | end |
38 | 103 |
|
| 104 | +# ====== Clone a few archived puzzles so the "hide cloned" filter has data ====== |
| 105 | +# Mix of pending and archived clones to exercise both states. |
| 106 | +cloned_sources = [ |
| 107 | + { question: "Ruby or Rails provided this method? before_action :authenticate_user!", state: :pending }, |
| 108 | + { question: "Ruby or Rails provided this method? User.where(active: true).order(:name)", state: :pending }, |
| 109 | + { question: "Ruby or Rails provided this method? 42.times { puts 'hello' }", state: :archived, sent_at: 12.hours.ago }, |
| 110 | + { question: "Ruby or Rails provided this method? flash[:notice] = 'Saved!'", state: :archived, sent_at: 6.hours.ago } |
| 111 | +] |
| 112 | + |
| 113 | +cloned_sources.each do |source| |
| 114 | + parent = Puzzle.find_by(question: source[:question]) |
| 115 | + next unless parent |
| 116 | + next if Puzzle.where(original_puzzle_id: parent.id).exists? |
| 117 | + |
| 118 | + Puzzle.create!( |
| 119 | + question: "#{parent.question} (clone)", |
| 120 | + answer: parent.answer, |
| 121 | + explanation: parent.explanation, |
| 122 | + link: parent.link, |
| 123 | + suggested_by: parent.suggested_by, |
| 124 | + state: source[:state], |
| 125 | + sent_at: source[:sent_at], |
| 126 | + original_puzzle: parent |
| 127 | + ) |
| 128 | +end |
| 129 | + |
39 | 130 | # ====== Create the Server ====== |
40 | 131 | server = Server.find_or_create_by!(server_id: 1179555097060061245) do |s| |
41 | 132 | s.name = "OmbuTest" |
|
63 | 154 |
|
64 | 155 | # Associate user with the server if not already linked |
65 | 156 | user.servers << server unless user.servers.include?(server) |
| 157 | +end |
| 158 | + |
| 159 | +# ====== Seed answers for archived puzzles ====== |
| 160 | +# Real users only answer puzzles after they've been sent (archived state). |
| 161 | +# For each archived puzzle, mark the first `success_rate / 10` users correct |
| 162 | +# and the rest incorrect, so each puzzle hits its target rate exactly. |
| 163 | +server_users = server.users.order(:id) |
| 164 | + |
| 165 | +Puzzle.archived.each do |puzzle| |
| 166 | + base_question = puzzle.original_puzzle&.question || puzzle.question |
| 167 | + correct_count = success_rate_by_question.fetch(base_question, 50) / 10 |
66 | 168 |
|
67 | | - # Seed random answers for this user if they have none |
68 | | - if user.answers.where(server_id: server.id).empty? |
69 | | - 3.times do |
70 | | - puzzle = Puzzle.all.sample |
71 | | - Answer.find_or_create_by!( |
72 | | - user_id: user.id, |
73 | | - puzzle_id: puzzle.id, |
74 | | - server_id: server.id |
75 | | - ) do |answer| |
76 | | - answer.choice = [ "ruby", "rails" ].sample |
77 | | - answer.is_correct = [ true, false ].sample |
78 | | - end |
| 169 | + server_users.each_with_index do |user, idx| |
| 170 | + Answer.find_or_create_by!( |
| 171 | + user_id: user.id, |
| 172 | + puzzle_id: puzzle.id, |
| 173 | + server_id: server.id |
| 174 | + ) do |answer| |
| 175 | + answer.choice = [ "ruby", "rails" ].sample |
| 176 | + answer.is_correct = idx < correct_count |
79 | 177 | end |
80 | 178 | end |
81 | 179 | end |
0 commit comments