[RUBY] Randomly select 100 records from DB

When I saved a certain data, I wanted to randomly associate 100 users with that data.

As a preparation, create a new table to link the "table that manages the saved data" and the "table that manages the user". Details will be explained later.

First, in the method that saves the original data, call the user-selected method.

if @item.save
      destination_select()

Next, we will write a method to select the user.

As a policy

① Prepare an empty array (2) Get the user id randomly using the rand function ③ If the acquired id is not included in the array, save it in addition to the array. ④ If it is included, redo the rand function </ b>

It will be.

Let's look at each one.

① Prepare an empty array </ b>

def destination_select
    user_ids = []                             
  end

② Get the user id randomly using the rand function </ b> The range is set with the number of records in the User model as the argument of the rand function. Also, this time I want to get 10 people, so I repeat this 10 times with the times method.

 def destination_select
    user_ids = []
    100.times do |i|
      user_id = (rand(User.count))
    end
  end

③ If the acquired id is not included in the array, save it in addition to the array I'm pushing the retrieved ids into the array user_ids. Also, in the "table for linking" prepared in advance here, Save the record with the id of @item defined by the caller and the user_id obtained by the rand function as arguments.
 def destination_select
    user_ids = []
    100.times do |i|
      user_id = (rand(User.count))
      #Describe the conditional expression of ④ here
      user_ids.push(user_id)
      Destination.create(item_id: @item.id, user_id: user_id)
    end
  end

④ If it is included, redo the rand function If this is left as it is, the user_id may be duplicated as a result of the rand function. Therefore, it is judged whether the id acquired by the include? Method does not overlap with the id acquired so far and noted in the array, and the rand function is repeated until there is no duplication.
 def destination_select
    user_ids = []
    100.times do |i|
      user_id = (rand(User.count))
      while user_ids.include?(user_id) do
        user_id = (rand(User.count)) 
      end
      user_ids.push(user_id)
      Destination.create(item_id: @item.id, user_id: user_id)
    end
  end

That's all there is to it.

6
8
42
85
93
75
5
40
79
23
17
13
88
74
54
62
64
26
35
70
14
49
63
28
81
98
69
94
0
91
87
55
84
83
9
36
80
78
30
12
3
92
20
24
2
67
34
43
16
95
86
38
22
77
97
11
25
21
90
1
51
65
53
68
37
58
56
47
18
15
41
29
89
59
52
44
46
48
82
57
10
50
45
60
66
7
32
76
4
19
27
61
96
39
71
72
33
31
99
73

I was able to randomly retrieve and save the ids for 100 people without duplication.

Postscript

As you pointed out in the comments, I would like to add two points.
(1) In the above case, 0 is included due to the nature of the rand function. Since the user_id of 0 does not exist, it is necessary to add +1. </ b>

(2) As a random acquisition method, the following is faster and simpler to describe. </ b>

User.order("random()").limit(100).pluck(:id) # sqlite/pg
User.order("rand()").limit(100).pluck(:id) # mysql
user_ids = User.order("random()").limit(100).pluck(:id)
user_ids.each{|user_id| Destination.create(item_id: @item.id, user_id: user_id) }

Thank you for pointing out.