简体   繁体   中英

Eager loading database table using ActiveRecord

I have a Ruby 2.2.2 app that uses ActiveRecord as the ORM (similar to Rails). I have two tables, "users" and "accounts", where "accounts" have belongs_to :user . For a given user, I simply want to eager load the contents of the "accounts" table into a Ruby object (named user_accounts ) so I can perform operations like:

user_accounts.find_by_product_name("nameofproduct")

...without the find_by_product_name method performing a SQL query. I simply want to preload all entries from the "accounts" table (that belong to a given user) into a Ruby object so I can minimize the number of SQL queries performed.

No matter how much documentation I read, I cannot figure out how to do this properly. Is this possible? If so, how?

If you don't want the ORM to re-query the database, then I think you are better of using the select method added by the Enumerable mixin. Because if you try to use the find_by_* methods, I think it will always send another query.

Here is an example of how it could be achieved.

# The accounts association will be loaded and cached the first time
@user.accounts.select { |account| account.name == "nameofproduct" }

# The next time, it is already loaded and will select from the previously loaded records
@user.accounts.select { |account| account.name == "nameofanotherproduct" }

I would store that accounts in a hash instead of an array , because lookups in a hash are much faster (in O(1) ) than in an array which only allows O(n) .

group_by helps you building that hash.

# assuming that @user.accounts returns all accounts
user_accounts = @user.accounts.group_by(&:name)

# querying the hash. use `first` to receive the first matching 
# account (even if there is only one)
user_accounts['nameofproduct'].first

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM