<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="https://publishpress.com/"
	>

<channel>
	<title>Rails7.1 Archives - Tomoshare</title>
	<atom:link href="https://blog.tomosia.com.vn/tag/rails7-1/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.tomosia.com.vn/tag/rails7-1/</link>
	<description>Kênh chia sẻ kiến thức Tomosia Việt Nam</description>
	<lastBuildDate>Thu, 18 Jan 2024 01:46:01 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://blog.tomosia.com.vn/wp-content/uploads/2023/09/cropped-icon-32x32.png</url>
	<title>Rails7.1 Archives - Tomoshare</title>
	<link>https://blog.tomosia.com.vn/tag/rails7-1/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>[Rails Tips] Rails 7.1 &#8211; ActiveRecord::QueryMethods#select has added support for hash values</title>
		<link>https://blog.tomosia.com.vn/rails-tips-rails-7-1-activerecordquerymethodsselect-has-added-support-for-hash-values/</link>
					<comments>https://blog.tomosia.com.vn/rails-tips-rails-7-1-activerecordquerymethodsselect-has-added-support-for-hash-values/#comments</comments>
		
		<dc:creator><![CDATA[Thuan Nguyen Van]]></dc:creator>
		<pubDate>Thu, 18 Jan 2024 01:45:59 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Rails7.1]]></category>
		<category><![CDATA[Ruby On Rails]]></category>
		<category><![CDATA[ActiveRecord]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=3011</guid>

					<description><![CDATA[<p>Trong bản cập nhật mới nhất của, Rails 7.1 đã cho phép chúng ta query select theo giá&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/rails-tips-rails-7-1-activerecordquerymethodsselect-has-added-support-for-hash-values/">[Rails Tips] Rails 7.1 &#8211; ActiveRecord::QueryMethods#select has added support for hash values</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Trong bản cập nhật mới nhất của, Rails 7.1 đã cho phép chúng ta query <strong>select</strong> theo giá trị hash chứ không cần phải sử dụng <strong>raw SQL</strong> nữa.</p>



<p>💎 Improvements:<br>1️⃣ New support query với giá trị <strong>Hash</strong><br>2️⃣ Chúng ta không cần phải dùng truy vấn <strong>raw version</strong> nữa</p>



<p>💎 Bonus:<br>1️⃣ Cú pháp mới cũng support chúng ta sử dụng <strong>alias</strong><br>2️⃣ Sử dụng tương tự cho ActiveRecord#reselect</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:16.859375px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">Ruby</span><span role="button" tabindex="0" data-code="# Before Rails 7.1

Post.joins(:comments)
    .select(
      &quot;posts.id as post_id, posts.title as post_title,
      comments.id as comment_id, comments.body as comment_body&quot;
    )
    
Post.joins(:comments).select(:id, :title, &quot;comments.body&quot;)

# After Rails 7.1

Post.joins(:comments)
    .select(
      posts: { id: :post_id, title: :post_title },
      comments: { id: :comments_id, body: :comment_body }
    )
    
Post.joins(:comments).select(:id, :title, comments: [:body] )" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #7B7F8B"># Before Rails 7.1</span></span>
<span class="line"></span>
<span class="line"><span style="color: #97E1F1; font-style: italic">Post</span><span style="color: #F6F6F4">.joins(</span><span style="color: #BF9EEE">:comments</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">    .</span><span style="color: #97E1F1">select</span><span style="color: #F6F6F4">(</span></span>
<span class="line"><span style="color: #F6F6F4">      </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">posts.id as post_id, posts.title as post_title,</span></span>
<span class="line"><span style="color: #E7EE98">      comments.id as comment_id, comments.body as comment_body</span><span style="color: #DEE492">&quot;</span></span>
<span class="line"><span style="color: #F6F6F4">    )</span></span>
<span class="line"><span style="color: #F6F6F4">    </span></span>
<span class="line"><span style="color: #97E1F1; font-style: italic">Post</span><span style="color: #F6F6F4">.joins(</span><span style="color: #BF9EEE">:comments</span><span style="color: #F6F6F4">).</span><span style="color: #97E1F1">select</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">:id</span><span style="color: #F6F6F4">, </span><span style="color: #BF9EEE">:title</span><span style="color: #F6F6F4">, </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">comments.body</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #7B7F8B"># After Rails 7.1</span></span>
<span class="line"></span>
<span class="line"><span style="color: #97E1F1; font-style: italic">Post</span><span style="color: #F6F6F4">.joins(</span><span style="color: #BF9EEE">:comments</span><span style="color: #F6F6F4">)</span></span>
<span class="line"><span style="color: #F6F6F4">    .</span><span style="color: #97E1F1">select</span><span style="color: #F6F6F4">(</span></span>
<span class="line"><span style="color: #F6F6F4">      posts</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> { id</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">:post_id</span><span style="color: #F6F6F4">, title</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">:post_title</span><span style="color: #F6F6F4"> },</span></span>
<span class="line"><span style="color: #F6F6F4">      comments</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> { id</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">:comments_id</span><span style="color: #F6F6F4">, body</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">:comment_body</span><span style="color: #F6F6F4"> }</span></span>
<span class="line"><span style="color: #F6F6F4">    )</span></span>
<span class="line"><span style="color: #F6F6F4">    </span></span>
<span class="line"><span style="color: #97E1F1; font-style: italic">Post</span><span style="color: #F6F6F4">.joins(</span><span style="color: #BF9EEE">:comments</span><span style="color: #F6F6F4">).</span><span style="color: #97E1F1">select</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">:id</span><span style="color: #F6F6F4">, </span><span style="color: #BF9EEE">:title</span><span style="color: #F6F6F4">, comments</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> [</span><span style="color: #BF9EEE">:body</span><span style="color: #F6F6F4">] )</span></span></code></pre></div>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="956" height="551" src="http://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screen-Shot-2024-01-02-at-14.42.49.png" alt="" class="wp-image-3016" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screen-Shot-2024-01-02-at-14.42.49.png 956w, https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screen-Shot-2024-01-02-at-14.42.49-300x173.png 300w, https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screen-Shot-2024-01-02-at-14.42.49-768x443.png 768w, https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screen-Shot-2024-01-02-at-14.42.49-380x219.png 380w, https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screen-Shot-2024-01-02-at-14.42.49-800x461.png 800w" sizes="(max-width: 956px) 100vw, 956px" /></figure>
<p>The post <a href="https://blog.tomosia.com.vn/rails-tips-rails-7-1-activerecordquerymethodsselect-has-added-support-for-hash-values/">[Rails Tips] Rails 7.1 &#8211; ActiveRecord::QueryMethods#select has added support for hash values</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/rails-tips-rails-7-1-activerecordquerymethodsselect-has-added-support-for-hash-values/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>Rails 7.1 đã cho phép ErrorReporter để handle error classes.</title>
		<link>https://blog.tomosia.com.vn/don-gian-hoa-xu-ly-rescue-trong-rails-7-1/</link>
					<comments>https://blog.tomosia.com.vn/don-gian-hoa-xu-ly-rescue-trong-rails-7-1/#comments</comments>
		
		<dc:creator><![CDATA[Nguyen Anh]]></dc:creator>
		<pubDate>Wed, 08 Nov 2023 06:19:54 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Rails7.1]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=1773</guid>

					<description><![CDATA[<p>ErrorReporter was added to Rails in version 7.0. It was introduced as a way to provide a more consistent and standardized way to handle errors in the Rails applications.</p>
<p>The post <a href="https://blog.tomosia.com.vn/don-gian-hoa-xu-ly-rescue-trong-rails-7-1/">Rails 7.1 đã cho phép ErrorReporter để handle error classes.</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p></p>



<p><strong>Before Rails 7.1</strong></p>



<pre class="wp-block-code"><code># to handle a single error
begin
  code_that_raises_exception
rescue ArgumentError =&gt; e
  puts e.message
end   

# to handle multiple errors
exceptions = &#91;ArgumentError, StandarError]

begin
  code_that_raises_argument_error
  code_that_raises_standard_error
rescue *exceptions =&gt; e
  puts "Error: #{e.message} occurred."
end</code></pre>



<p><strong>In Rails 7.1</strong></p>



<pre class="wp-block-code"><code>@post = Post.new(params&#91;:post])

Rails.error.handle(ActiveRecord::Errors, StandardError) do
  @post.save!
end</code></pre>



<p><em><a href="https://github.com/rails/rails/pull/46299">PR of the update</a></em></p>
<p>The post <a href="https://blog.tomosia.com.vn/don-gian-hoa-xu-ly-rescue-trong-rails-7-1/">Rails 7.1 đã cho phép ErrorReporter để handle error classes.</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/don-gian-hoa-xu-ly-rescue-trong-rails-7-1/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Tìm hiểu find_each, find_in_batches và in_batches</title>
		<link>https://blog.tomosia.com.vn/tim-hieu-find_each-find_in_batches-va-in_batches/</link>
					<comments>https://blog.tomosia.com.vn/tim-hieu-find_each-find_in_batches-va-in_batches/#comments</comments>
		
		<dc:creator><![CDATA[Vu Nguyen Duy]]></dc:creator>
		<pubDate>Tue, 31 Oct 2023 02:03:24 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Rails7.1]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=1614</guid>

					<description><![CDATA[<p>Khi làm việc với dữ liệu lớn trong ứng dụng Ruby on Rails, việc truy vấn và xử&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/tim-hieu-find_each-find_in_batches-va-in_batches/">Tìm hiểu find_each, find_in_batches và in_batches</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Khi làm việc với dữ liệu lớn trong ứng dụng Ruby on Rails, việc truy vấn và xử lý hàng loạt dữ liệu có thể trở nên phức tạp. Để giải quyết vấn đề này, Rails cung cấp các phương thức quan trọng: <code>find_each</code>, <code>find_in_batches</code>, <code>in_batches</code>. Trong bài viết này, chúng ta sẽ tìm hiểu về cách sử dụng chúng.</p>



<h2 id="1-find_each" class="wp-block-heading"><strong>1.find_each:</strong></h2>



<ul class="wp-block-list">
<li><code>find_each</code> là một phương thức mạnh mẽ giúp bạn truy vấn và xử lý hàng loạt dữ liệu một cách hiệu quả. Thay vì lấy toàn bộ kết quả truy vấn vào bộ nhớ và xử lý cùng một lúc, <code>find_each</code> cho phép bạn truy vấn từng phần dữ liệu nhỏ, tiết kiệm tài nguyên hệ thống.</li>



<li>Ví dụ sử dụng <code>find_each</code>:<br></li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#F8F8F2;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#efefe1">Ruby</span><span role="button" tabindex="0" data-code="User.find_each(batch_size: 1000) do |user|
  # Xử lý dữ liệu của user
end" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #8BE9FD; font-style: italic">User</span><span style="color: #F8F8F2">.find_each(batch_size</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">1000</span><span style="color: #F8F8F2">) </span><span style="color: #FF79C6">do</span><span style="color: #F8F8F2"> |user|</span></span>
<span class="line"><span style="color: #F8F8F2">  </span><span style="color: #6272A4"># Xử lý dữ liệu của user</span></span>
<span class="line"><span style="color: #FF79C6">end</span></span></code></pre></div>



<p>Trong ví dụ trên, <code>batch_size</code> xác định số lượng bản ghi được truy vấn và xử lý trong mỗi lần lặp. Điều này giúp giảm áp lực lên bộ nhớ và tăng hiệu suất xử lý.<br></p>



<h2 id="2-find_in_batches" class="wp-block-heading">2. <strong>find_in_batches:</strong></h2>



<ul class="wp-block-list">
<li><code>find_in_batches</code> là một phương thức tương tự như <code>find_each</code>, nhưng thay vì lặp qua từng bản ghi, nó trả về từng batch (nhóm) bản ghi mà bạn có thể xử lý một cách đồng thời.</li>



<li>Ví dụ sử dụng <code>find_in_batches</code>:</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#F8F8F2;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#efefe1">Ruby</span><span role="button" tabindex="0" data-code="User.find_in_batches(batch_size: 200) do |users|
  users.each do |user|
    # Xử lý dữ liệu của user
  end
end" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #8BE9FD; font-style: italic">User</span><span style="color: #F8F8F2">.find_in_batches(batch_size</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">200</span><span style="color: #F8F8F2">) </span><span style="color: #FF79C6">do</span><span style="color: #F8F8F2"> |users|</span></span>
<span class="line"><span style="color: #F8F8F2">  users.each </span><span style="color: #FF79C6">do</span><span style="color: #F8F8F2"> |user|</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #6272A4"># Xử lý dữ liệu của user</span></span>
<span class="line"><span style="color: #F8F8F2">  </span><span style="color: #FF79C6">end</span></span>
<span class="line"><span style="color: #FF79C6">end</span></span></code></pre></div>



<ul class="wp-block-list">
<li>Những option được sử dụng trong find_each và find_in_batches
<ul class="wp-block-list">
<li><code>batch_size:</code> là kích thước chỉ định của batch. Mặc định là 1000.</li>



<li><code>start: </code>Chỉ định primary_key bắt đầu trong batch, ví dụ bạn muốn lấy từ id = 5000, thì batch của bạn sẽ bắt đầu từ 5000</li>



<li><code>finish:</code> Chỉ định giá trị primary_key để kết thúc, như ở option :start là chọn vị trị bắt đầu thì :finish sẽ là vị trị kết thúc của batch.</li>
</ul>
</li>
</ul>



<h2 id="3-in_batches-trong-rails-7-1" class="wp-block-heading"><strong>3. in_batches trong rails 7.1</strong></h2>



<ul class="wp-block-list">
<li>Các bạn có thể thấy lợi ích của việc sử dụng find_each và find_in_batches ở trên, nhưng nó có hạn chế, việc sắp xếp các record chỉ dựa vào id của bảng và theo mặc định tăng dần, chúng ta không thể sắp xếp theo các trường khác. Thật may mắn trong ở phiên bản  rails 7.1 chúng ta có in_batches cho phép chúng ta sắp xếp theo các column mong muốn.</li>



<li>Ví dụ, nếu bạn muốn sắp xếp các bản ghi theo cột&nbsp;<code>created_at</code>, bạn có thể sử dụng&nbsp;<code>in_batches</code>&nbsp;như sau:</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#F8F8F2;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#efefe1">Ruby</span><span role="button" tabindex="0" data-code="User.in_batches(of: 1000, order: :created_at) do |batch|
  batch.each do |user|
    # Do something with each user
  end
end
" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #8BE9FD; font-style: italic">User</span><span style="color: #F8F8F2">.in_batches(of</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">1000</span><span style="color: #F8F8F2">, order</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">:created_at</span><span style="color: #F8F8F2">) </span><span style="color: #FF79C6">do</span><span style="color: #F8F8F2"> |batch|</span></span>
<span class="line"><span style="color: #F8F8F2">  batch.each </span><span style="color: #FF79C6">do</span><span style="color: #F8F8F2"> |user|</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #6272A4"># Do something with each user</span></span>
<span class="line"><span style="color: #F8F8F2">  </span><span style="color: #FF79C6">end</span></span>
<span class="line"><span style="color: #FF79C6">end</span></span>
<span class="line"></span></code></pre></div>



<ul class="wp-block-list">
<li>Các option hỗ trợ trong in_batches:
<ul class="wp-block-list">
<li><code>of:</code> Số lượng bản ghi tối đa trong mỗi batch.&nbsp;Giá trị mặc định là 1000</li>



<li><code>start:</code> Giá trị khóa chính của bản ghi đầu tiên trong batch.&nbsp;Giá trị mặc định là&nbsp;<code>nil</code>.</li>



<li><code>finish:</code> Giá trị khóa chính của bản ghi cuối cùng trong batch.&nbsp;Giá trị mặc định là&nbsp;<code>nil.</code></li>



<li><code>order:</code> Cột sắp xếp các bản ghi trong batch. Giá trị mặc định là&nbsp;<code>nil</code>.<br></li>
</ul>
</li>
</ul>



<p><strong>NOTE: một vài lưu ý khi sử dụng in_batches:</strong><br></p>



<ul class="wp-block-list">
<li>Nếu bạn không chỉ định cột sắp xếp,&nbsp;<code>in_batches</code>&nbsp;sẽ sắp xếp các bản ghi theo khóa chính của chúng.</li>



<li>Nếu bạn chỉ định cột sắp xếp, hãy đảm bảo rằng cột đó đã được đánh index để tối ưu hóa hiệu suất.</li>



<li>Nếu bạn muốn thực hiện các thao tác cập nhật hoặc xóa trên các bản ghi, hãy đảm bảo rằng bạn đã sử dụng&nbsp;<code>update_all</code>&nbsp;hoặc&nbsp;<code>delete_all</code>&nbsp;để tránh lỗi(áp dụng cho cả find_in_batches), ví dụ: <br></li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#F8F8F2;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#efefe1">Ruby</span><span role="button" tabindex="0" data-code="User.in_batches.each do |batch|
  batch.update_all('age = age + 5')
  batch.where('age &gt; 25').update_all(is_married: true)
  batch.where('age &lt;= 25').delete_all
end" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #8BE9FD; font-style: italic">User</span><span style="color: #F8F8F2">.in_batches.each </span><span style="color: #FF79C6">do</span><span style="color: #F8F8F2"> |batch|</span></span>
<span class="line"><span style="color: #F8F8F2">  batch.update_all(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">age = age + 5</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">)</span></span>
<span class="line"><span style="color: #F8F8F2">  batch.where(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">age &gt; 25</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">).update_all(is_married</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">true</span><span style="color: #F8F8F2">)</span></span>
<span class="line"><span style="color: #F8F8F2">  batch.where(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">age &lt;= 25</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">).delete_all</span></span>
<span class="line"><span style="color: #FF79C6">end</span></span></code></pre></div>



<p></p>



<p></p>



<div class="wp-block-cover is-light"><span aria-hidden="true" class="wp-block-cover__background has-cyan-bluish-gray-background-color has-background-dim-100 has-background-dim"></span><div class="wp-block-cover__inner-container is-layout-constrained wp-block-cover-is-layout-constrained">
<p class="has-text-align-center has-medium-font-size">Hi vọng bài viết có thể giúp ích cho các bạn. Chúc các bạn luôn tìm được niềm vui khi coding. 😀</p>
</div></div>
<p>The post <a href="https://blog.tomosia.com.vn/tim-hieu-find_each-find_in_batches-va-in_batches/">Tìm hiểu find_each, find_in_batches và in_batches</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/tim-hieu-find_each-find_in_batches-va-in_batches/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>Rails 7.1: Mở Rộng khả Năng bảo mật với generates_token_for và signed_id</title>
		<link>https://blog.tomosia.com.vn/rails-7-1-mo-rong-kha-nang-bao-mat-voi-generates_token_for-va-signed_id/</link>
					<comments>https://blog.tomosia.com.vn/rails-7-1-mo-rong-kha-nang-bao-mat-voi-generates_token_for-va-signed_id/#comments</comments>
		
		<dc:creator><![CDATA[Minh Tang]]></dc:creator>
		<pubDate>Tue, 24 Oct 2023 17:05:43 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Rails7.1]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=1491</guid>

					<description><![CDATA[<p>Việc tạo ra những token đặc biệt, an toàn và có thể chứa thông tin về mục đích&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/rails-7-1-mo-rong-kha-nang-bao-mat-voi-generates_token_for-va-signed_id/">Rails 7.1: Mở Rộng khả Năng bảo mật với generates_token_for và signed_id</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Việc tạo ra những token đặc biệt, an toàn và có thể chứa thông tin về mục đích sử dụng cũng như thời gian hết hạn của token rất hữu ích trong một số tình huống cụ thể. Bạn có thể tạo ra một token duy nhất cho các mục đích cụ thể như <strong>authenticate access_token, reset email</strong> hoặc <strong>reset password</strong>, sau đó gán chúng vào địa chỉ URL của ứng dụng của bạn và gửi cho người dùng qua email.</p>



<h2 id="su-dung-activerecordsignedid" class="wp-block-heading">Sử dụng ActiveRecord:SignedId</h2>



<p>Từ bây giờ bạn có thể sử dụng API <code>ActiveRecord::SignedId</code> để tạo ra các token có thời hạn. Và bạn có thể dùng ActiveRecord để tìm bản ghi sử dụng signed id tương ứng</p>



<p>Hãy xem xét một tình huống trong đó chúng ta muốn gửi một liên kết đặt lại mật khẩu cho người dùng. Nếu bạn muốn tạo ra một token duy nhất có hiệu lực trong vòng 1 ngày.</p>



<pre class="wp-block-code"><code>user = User.first
signed_id = user.signed_id(expires_in: 1.day, purpose: :password_reset)

# Output signed_id
# eyJfcmFpbHMiOnsiZGF0YSI6ODg3LCJleHAiOiIyMDIzLTEwLTI1VDE2OjM2OjI4LjY1MloiLCJwdXIiOiJ1c2VyL3Bhc3N3b3JkX3Jlc2V0In19--4b1bde069dad4fa959fc111dbb401fac724cd43ab7aea772841fc90d87e42354
</code></pre>



<p>Mã <code>signed_id</code> trên sẽ có thời hạn 1 ngày và mục đích (purpose) chúng ta có thể ghi bất kỳ thứ gì củng được. Sau đó để tìm lại record từ signed_id trên thì làm như sau:</p>



<pre class="wp-block-code"><code>User.find_signed(signed_id, purpose: :password_reset)

# Output
# &lt;User:0x000000010ed60a38
</code></pre>



<p>Vì ở trên khi signed_id ta có điền purpose thì khi find chúng ta củng phải truyền lại purpose. Trường hợp không đúng thì kết quả sẽ trả về <code>nil</code>, còn khi hết hạn sẽ raise lỗi</p>



<h2 id="su-dung-activerecordbasegenerates_token_for" class="wp-block-heading">Sử dụng ActiveRecord::Base::generates_token_for</h2>



<pre class="wp-block-code"><code>class User &lt; ActiveRecord::Base
  has_secure_password

  generates_token_for :password_reset, expires_in: 1.day do
    BCrypt::Password.new(password_digest).salt&#91;-10..]
  end
end
</code></pre>



<p>Khởi tạo token</p>



<pre class="wp-block-code"><code>user = User.first
token = user.generate_token_for(:password_reset)

# Output
# eyJfcmFpbHMiOnsiZGF0YSI6Wzg4Nywid3FxLlhwdWJjLiJdLCJleHAiOiIyMDIzLTEwLTI0VDE2OjU0OjA5LjU0MloiLCJwdXIiOiJVc2VyXG5wYXNzd29yZF9yZXNldFxuNjAifX0=--8430fc9ee974752f075c78c6d...

</code></pre>



<p>Tìm record từ token đã tạo ở trên</p>



<pre class="wp-block-code"><code>User.find_by_token_for(:password_reset, token)
# Output:
# &lt;User:0x000000010ed60a38
</code></pre>



<p><code>generates_token_for</code> hoạt động tương tự như <code>signed_id</code>. Trong khi <code>signed_id</code> sử dụng model ID làm dữ liệu đầu vào, thì <code>generates_token_for</code> sử dụng sự kết hợp giữa model ID và giá trị được trả về bởi block. Block này nên tham chiếu tới một thuộc tính liên quan đến mục đích của token (Ở đây là <code>password_digest</code>). Khi thuộc tính này (password_digest) được cập nhật, dữ liệu đầu vào cũng được cập nhật và từ đó làm vô hiệu hóa token cũ.</p>



<p>Trong ví dụ trên, sự kết hợp dữ liệu đầu vào sẽ là model ID và 10 ký tự cuối cùng của Bycrypt Password</p>



<p>Khi bạn cập nhật mật khẩu, thì <code>password_digest</code> sẽ thay đổi và do đó token bị vô hiệu hóa sau lần cập nhật đầu tiên của mật khẩu. Điều này khiến cho token chỉ có thể được sử dụng một lần.</p>



<p>Trước đây với bài toán <code>reset password</code> hay <code>reset email</code> thông thường ta sẽ tạo ra 2 cột để lưu trữ (reset_email_token và reset_email_token_expired). Bây giờ sẽ không cần nửa bởi vì đã có <code>generates_token_for</code></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p><em>Cảm ơn bạn đã đọc bài viết này về tính năng <code>generates_token_for</code> và <code>signed_id</code> trong Rails 7.1. Hy vọng rằng bạn đã tìm thấy thông tin hữu ích và có thêm kiến thức về cách sử dụng tính năng này để tạo ra các token đặc biệt và an toàn trong ứng dụng của mình. Nếu bạn có bất kỳ câu hỏi hoặc góp ý nào, đừng ngần ngại chia sẻ. Chúng tôi luôn đánh giá phản hồi từ độc giả. Hãy tiếp tục theo dõi và chia sẻ kiến thức về lĩnh vực phát triển ứng dụng web. Cảm ơn bạn đã ủng hộ!</em></p>
<p>The post <a href="https://blog.tomosia.com.vn/rails-7-1-mo-rong-kha-nang-bao-mat-voi-generates_token_for-va-signed_id/">Rails 7.1: Mở Rộng khả Năng bảo mật với generates_token_for và signed_id</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/rails-7-1-mo-rong-kha-nang-bao-mat-voi-generates_token_for-va-signed_id/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
	</channel>
</rss>
