gclement
gclement

Reputation: 93

Optimize big array search ruby

I am creating a friendship feature. But I have an issue. When a user is sending a request to a specific user, it is iterating through more than 3k users in order to find the right person. I'd like to know if there is a ruby method which permits to increase the speed of the search.

I'm using the has_friendship gem

Here is my code : View friends : index.html.erb


<div class="info  d-flex  flex-column">
    <header class="ui basic segment">
      <h3 class="typo text-center mt-2">Ajoutes tes amis 👇</h3>
    </header>
    <div class="ui basic segment">
      <%= form_tag ({controller: 'friends', action: 'search'}) do %>
        <div class="text-center mt-2">
          <input type="align-items-center mt-2" name="search" id="search">
        </div>
        <input class="btn btn-light mt-3" type="submit" name="commit" value="Chercher" data-disable-with="Search">
      <% end %>
    </div>
  </div>

Here is my controller of friends with the method search :

@search = params[:search]
@results = User.find{|x| x.pseudo == @search}

Here is my search view : search.html.erb


<% if @results.name != current_user.name %>
 <div class="ui vertical clearing segment">
   <span class="ui header">
    <p class="typopo"> Pseudo: <%= @results.pseudo %></p>
    <p class="typopo"> Championnat: <%= @results.player_seasons[0].championship.name %></p>
    <p class="typopo"> Nombre de points: <%= @results.player_seasons[0].number_of_points %></p>
   </span>
  <% if current_user.not_friends.include?(@results) %>
   <div class="ui basic segment">
    <%= form_tag ({controller: 'friends', action: 'create', method: 'post', id: @results.id}) do %>
    <input class="btn btn-light mt-3" type=submit value='Ajouter'>
   <% end %>
  </div>
 <% end %>
 <% end %>

Here is my schema for the user model and the friendship model :

create_table "friendships", id: :serial, force: :cascade do |t|
    t.string "friendable_type"
    t.integer "friendable_id"
    t.integer "friend_id"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer "blocker_id"
    t.integer "status"
    t.index ["friendable_id", "friend_id"], name: "index_friendships_on_friendable_id_and_friend_id", unique: true
  end

create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.string "name"
    t.string "pseudo"
    t.string "last_name"
    t.boolean "admin", default: false, null: false
    t.string "blason"
    t.string "provider"
    t.string "uid"
    t.text "image"
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

Thank you by advance

Upvotes: 1

Views: 212

Answers (2)

Sebasti&#225;n Palma
Sebasti&#225;n Palma

Reputation: 33420

As you're filtering records by their pseudo column, in its entirety, you could use find_by, which implements the WHERE clause plus a LIMIT of 1:

User.find_by(pseudo: @search)

Upvotes: 2

I think you can try save user.pseudo to db and search by that field. You can improve speed with db index.

Upvotes: 0

Related Questions