Sử dụng selecbox và cache giá trị selecbox trong Rails
Bài đăng này đã không được cập nhật trong 6 năm
Việc sử dụng selectbox trong hiển thị dự liệu là khá phổ biến và dễ dàng, nhưng đôi lúc ta quên mất xét hiệu năng sử dụng của nó. Để tăng tính hiệu quả trong sử dụng selectbox mình xin chia sẻ một thủ thuật nhỏ sưu tầm được.
Tạo database test:
- category model:
class CreateCategory < ActiveRecord::Migration
def change
create_table :category do |t|
t.string :name
t.timestamps null: false
end
end
end
- book model:
class CreateBook < ActiveRecord::Migration
def change
create_table :book do |t|
t.references :category, index: true, foreign_key: true
t.string :name
t.timestamps null: false
end
end
end
Giả sử ta muốn hiển thị tất các course dạng selectbox trong views/books/index.html.erb.
- bookscontroller.rb :
def index
@categories = Category.all
end
- views/books/index.html.erb
<%= select("book", "category_id", @categories.collect {|category| [ category.name, category.id ] }, { include_blank: true }) %>
OR
<%= select_tag "category_id", options_from_collection_for_select(@categories, "id", "name") %>
Nhưng điều gì sẽ xảy ra nếu số lượng Category.all khá lớn ?
Để hạn chế việc liên tục load Category.all vào selectbox ta cần cache nó lại
Cache data trong selectbox
- Ta tạo một file models/concerns/actsasoptionsprovider.rb
module ActsAsOptionsProvider
CACHE_OPTION = {expires_in: 30.minutes} # thoi gian cache
extend ActiveSupport::Concern
included do
after_commit{Rails.cache.delete "#{self.class.name}_options"} # *xoa cache khi co su thay doi record*
acts_as_options_provider
end
class_methods do
def acts_as_options_provider *attrs
options = attrs.last.is_a?(Hash) ? attrs.pop : CACHE_OPTION
attrs = [:name, :id] if attrs.empty?
key_name = "#{name}_options"
method_name = options.delete(:method_name) || :options
singleton_class.send :define_method, method_name, -> do
Rails.cache.fetch key_name, options do
pluck(*attrs)
end
end
end
end
end
- /models/category.rb
class Category< ApplicationRecord
include ActsAsOptionsProvider
....
- Xem sự khác biệt giá trị trả về của @categories
#Category.all
[51] pry(main)> Category.all
(0.2ms) SET NAMES utf8mb4 COLLATE utf8mb4_bin, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
Course Load (0.2ms) SELECT `categories`.* FROM `categories`
=> [#<Category:0x00556e5a8c42e0 id: 1, name: "Category-1", created_at: 2017-12-11 10:59:29 UTC, updated_at: 2017-12-11 10:59:29 UTC>,
#<Category:0x00556e5a8c0410 id: 2, name: "Category-3", created_at: 2017-12-11 10:59:34 UTC, updated_at: 2017-12-11 10:59:34 UTC>,
#<Category:0x00556e5a8c02d0 id: 3, name: "Category-4", created_at: 2017-12-11 10:59:37 UTC, updated_at: 2017-12-11 10:59:37 UTC>]
#Category.options
[52] pry(main)> Category.options
(0.4ms) SELECT `categories`.`name`, `categories`.`id` FROM `categories`
=> [["Category-1", 1], ["Category-3", 2], ["Category-4", 3]]
- bookscontroller.rb
def index
@categories = Category.options
end
- views/books/index.html.erb
<%= select_tag "category_id", options_from_collection_for_select(@categories) %>
Link tham khảo:
https://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/select https://apidock.com/rails/ActionView/Helpers/FormTagHelper/select_tag
All rights reserved