<?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>Minh Tang, Author at Tomoshare</title>
	<atom:link href="https://blog.tomosia.com.vn/author/minhtang/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.tomosia.com.vn/author/minhtang/</link>
	<description>Kênh chia sẻ kiến thức Tomosia Việt Nam</description>
	<lastBuildDate>Tue, 19 Dec 2023 04:02:35 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.3</generator>

<image>
	<url>https://blog.tomosia.com.vn/wp-content/uploads/2023/09/cropped-icon-32x32.png</url>
	<title>Minh Tang, Author at Tomoshare</title>
	<link>https://blog.tomosia.com.vn/author/minhtang/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Docker tips</title>
		<link>https://blog.tomosia.com.vn/docker-tips/</link>
					<comments>https://blog.tomosia.com.vn/docker-tips/#comments</comments>
		
		<dc:creator><![CDATA[Minh Tang]]></dc:creator>
		<pubDate>Tue, 19 Dec 2023 03:57:59 +0000</pubDate>
				<category><![CDATA[Infrastructure]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=2712</guid>

					<description><![CDATA[<p>Setting tag on an image Get bash inside runned container Clear docker unused images Clear docker exited containers&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/docker-tips/">Docker tips</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Setting tag on an image</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: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:#ebebe6">Bash</span><span role="button" tabindex="0" data-code="sudo docker tag 5db5f8471261 rhrn/ubuntu:webdev" 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: #62E884">sudo</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">docker</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">tag</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">5</span><span style="color: #E7EE98">db5f8471261</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">rhrn/ubuntu:webdev</span></span></code></pre></div>



<p class="wp-block-paragraph">Get bash inside runned container</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: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:#ebebe6">Bash</span><span role="button" tabindex="0" data-code="sudo docker exec -i -t 665b4a1e17b6 bash" 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: #62E884">sudo</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">docker</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">exec</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">-i</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">-t</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">665</span><span style="color: #E7EE98">b4a1e17b6</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">bash</span></span></code></pre></div>



<p class="wp-block-paragraph">Clear docker unused images</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: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:#ebebe6">Bash</span><span role="button" tabindex="0" data-code="docker rmi $(docker images -f &quot;dangling=true&quot; -q)" 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: #62E884">docker</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">rmi</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">$(</span><span style="color: #62E884">docker</span><span style="color: #E7EE98"> images </span><span style="color: #BF9EEE">-f</span><span style="color: #E7EE98"> </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">dangling=true</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98"> </span><span style="color: #BF9EEE">-q</span><span style="color: #E7EE98">)</span></span></code></pre></div>



<p class="wp-block-paragraph">Clear docker exited containers</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: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:#ebebe6">Bash</span><span role="button" tabindex="0" data-code="docker rm $(docker ps -aq -f status=exited)" 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: #62E884">docker</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">rm</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">$(</span><span style="color: #62E884">docker</span><span style="color: #E7EE98"> ps </span><span style="color: #BF9EEE">-aq</span><span style="color: #E7EE98"> </span><span style="color: #BF9EEE">-f</span><span style="color: #E7EE98"> status=exited)</span></span></code></pre></div>



<p class="wp-block-paragraph">Clear unused volumes</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: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:#ebebe6">Bash</span><span role="button" tabindex="0" data-code="docker volume ls -qf dangling=true | xargs -r docker volume rm" 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: #62E884">docker</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">volume</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">ls</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">-qf</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">dangling=</span><span style="color: #BF9EEE">true</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">|</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">xargs</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">-r</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">docker</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">volume</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">rm</span></span></code></pre></div>



<p class="wp-block-paragraph">Sort images by size</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:-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:#ebebe6">Bash</span><span role="button" tabindex="0" data-code="docker images --format &quot;{{.ID}}\\t{{.Size}}\\t{{.Repository}}&quot; | sort -k 2 -h" 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: #62E884">docker</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">images</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">--format</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">{{.ID}}</span><span style="color: #F286C4">\\</span><span style="color: #E7EE98">t{{.Size}}</span><span style="color: #F286C4">\\</span><span style="color: #E7EE98">t{{.Repository}}</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">|</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">sort</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">-k</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">2</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">-h</span></span></code></pre></div>
<p>The post <a href="https://blog.tomosia.com.vn/docker-tips/">Docker tips</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/docker-tips/feed/</wfw:commentRss>
			<slash:comments>15</slash:comments>
		
		
			</item>
		<item>
		<title>Rails console command made easier</title>
		<link>https://blog.tomosia.com.vn/rails-console-command-made-easier/</link>
					<comments>https://blog.tomosia.com.vn/rails-console-command-made-easier/#comments</comments>
		
		<dc:creator><![CDATA[Minh Tang]]></dc:creator>
		<pubDate>Tue, 12 Dec 2023 02:20:26 +0000</pubDate>
				<category><![CDATA[Chưa phân loại]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=2546</guid>

					<description><![CDATA[<p>Command trong rails thực sự rất là nhiều và củng không nhớ hết được syntax. Đâu đó thì&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/rails-console-command-made-easier/">Rails console command made easier</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Command trong rails thực sự rất là nhiều và củng không nhớ hết được syntax. Đâu đó thì củng chỉ nhớ được 1 vài task hay dùng, thay vì mỗi lần như vậy mình phải gõ cmd <code>bin/rails -T</code> để xem các command line có sẵn</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="rails db:create # Creates the database from DATABASE_URL or config/database.yml for the current RAILS_...
rails db:drop # Drops the database from DATABASE_URL or config/database.yml for the current RAILS_EN...
rails db:encryption:init  # Generate a set of keys for configuring Active Record encryption in a given environment
rails db:environment:set  # Set the environment value for the database
rails db:fixtures:load  # Loads fixtures into the current environment's database
rails db:migrate  # Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)
rails db:migrate:down # Runs the &quot;down&quot; for a given migration VERSION
rails db:migrate:redo # Rolls back the database one migration and re-migrates up (options: STEP=x, VERSION=x)
rails db:migrate:status # Display status of migrations
rails db:migrate:up # Runs the &quot;up&quot; for a given migration VERSION
rails db:prepare # Runs setup if database does not exist, or runs migrations if it does
rails db:reset # Drops and recreates all databases from their schema for the current environment and ...
rails db:rollback # Rolls the schema back to the previous version (specify steps w/ STEP=n)
rails db:schema:cache:clear # Clears a db/schema_cache.yml file
rails db:schema:cache:dump  # Creates a db/schema_cache.yml file
rails db:schema:dump  # Creates a database schema file (either db/schema.rb or db/structure.sql, depending on...
rails db:schema:load  # Loads a database schema file (either db/schema.rb or db/structure.sql, depending on ...
rails db:seed # Loads the seed data from db/seeds.rb
rails db:seed:replant # Truncates tables of each database for current environment and loads the seeds
rails db:setup  # Creates all databases, loads all schemas, and initializes with the seed data (use db...
rails db:version  # Retrieves the current schema version number
rails test:db # Run tests quickly, but also reset db" 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: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">create </span><span style="color: #7B7F8B"># Creates the database from DATABASE_URL or config/database.yml for the current RAILS_...</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">drop </span><span style="color: #7B7F8B"># Drops the database from DATABASE_URL or config/database.yml for the current RAILS_EN...</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">encryption</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">init  </span><span style="color: #7B7F8B"># Generate a set of keys for configuring Active Record encryption in a given environment</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">environment</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">set  </span><span style="color: #7B7F8B"># Set the environment value for the database</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">fixtures</span><span style="color: #F286C4">:</span><span style="color: #97E1F1">load</span><span style="color: #F6F6F4">  </span><span style="color: #7B7F8B"># Loads fixtures into the current environment&#39;s database</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">migrate  </span><span style="color: #7B7F8B"># Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">migrate</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">down </span><span style="color: #7B7F8B"># Runs the &quot;down&quot; for a given migration VERSION</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">migrate</span><span style="color: #F286C4">:redo</span><span style="color: #F6F6F4"> </span><span style="color: #7B7F8B"># Rolls back the database one migration and re-migrates up (options: STEP=x, VERSION=x)</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">migrate</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">status </span><span style="color: #7B7F8B"># Display status of migrations</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">migrate</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">up </span><span style="color: #7B7F8B"># Runs the &quot;up&quot; for a given migration VERSION</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">prepare </span><span style="color: #7B7F8B"># Runs setup if database does not exist, or runs migrations if it does</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">reset </span><span style="color: #7B7F8B"># Drops and recreates all databases from their schema for the current environment and ...</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">rollback </span><span style="color: #7B7F8B"># Rolls the schema back to the previous version (specify steps w/ STEP=n)</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">schema</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">cache</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">clear </span><span style="color: #7B7F8B"># Clears a db/schema_cache.yml file</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">schema</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">cache</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">dump  </span><span style="color: #7B7F8B"># Creates a db/schema_cache.yml file</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">schema</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">dump  </span><span style="color: #7B7F8B"># Creates a database schema file (either db/schema.rb or db/structure.sql, depending on...</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">schema</span><span style="color: #F286C4">:</span><span style="color: #97E1F1">load</span><span style="color: #F6F6F4">  </span><span style="color: #7B7F8B"># Loads a database schema file (either db/schema.rb or db/structure.sql, depending on ...</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">seed </span><span style="color: #7B7F8B"># Loads the seed data from db/seeds.rb</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">seed</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">replant </span><span style="color: #7B7F8B"># Truncates tables of each database for current environment and loads the seeds</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">setup  </span><span style="color: #7B7F8B"># Creates all databases, loads all schemas, and initializes with the seed data (use db...</span></span>
<span class="line"><span style="color: #F6F6F4">rails db</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">version  </span><span style="color: #7B7F8B"># Retrieves the current schema version number</span></span>
<span class="line"><span style="color: #F6F6F4">rails test</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4">db </span><span style="color: #7B7F8B"># Run tests quickly, but also reset db</span></span></code></pre></div>



<p class="wp-block-paragraph">Thay vì phải nhớ hết như vậy thì ta nên thiết lập alias cho đơn giản.</p>



<p class="wp-block-paragraph">Thiết lập alias tại: <code>vi ~/.bashrc</code></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="alias br='bin/rails'
alias be='bundle exec'
alias brdm='bin/rails db:migrate RAILS_ENV=development &amp;&amp; bin/rails db:migrate RAILS_ENV=test'
alias brdrol='bin/rails db:rollback STEP=1 &amp;&amp; bin/rails db:rollback STEP=1 RAILS_ENV=test'
alias bi='bundle install'
alias ees=&quot;export EDITOR='subl -w'&quot;
alias bd=&quot;./bin/dev&quot;
alias brdcm=&quot;br db:drop db:create db:migrate&quot;
alias brdcms=&quot;br db:drop db:create db:migrate db:seed&quot;
alias rcr=&quot;bin/rails cypress:run&quot;
alias rco=&quot;bin/rails cypress:open&quot;
alias resetdbtest='bin/rails db:drop db:create db:migrate RAILS_ENV=test'
alias resetdbdev='bin/rails db:drop db:create db:migrate RAILS_ENV=development'
alias brg='bin/rails generate'
alias brt='bin/rails test'
alias fd=&quot;foreman start -f Procfile.dev&quot;" 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: #F286C4">alias</span><span style="color: #F6F6F4"> br</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">bin/rails</span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #F286C4">alias</span><span style="color: #F6F6F4"> be</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">bundle exec</span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #F286C4">alias</span><span style="color: #F6F6F4"> brdm</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">bin/rails db:migrate RAILS_ENV=development &amp;&amp; bin/rails db:migrate RAILS_ENV=test</span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #F286C4">alias</span><span style="color: #F6F6F4"> brdrol</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">bin/rails db:rollback STEP=1 &amp;&amp; bin/rails db:rollback STEP=1 RAILS_ENV=test</span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #F286C4">alias</span><span style="color: #F6F6F4"> bi</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">bundle install</span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #F286C4">alias</span><span style="color: #F6F6F4"> ees</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">export EDITOR=&#39;subl -w&#39;</span><span style="color: #DEE492">&quot;</span></span>
<span class="line"><span style="color: #F286C4">alias</span><span style="color: #F6F6F4"> bd</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">./bin/dev</span><span style="color: #DEE492">&quot;</span></span>
<span class="line"><span style="color: #F286C4">alias</span><span style="color: #F6F6F4"> brdcm</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">br db:drop db:create db:migrate</span><span style="color: #DEE492">&quot;</span></span>
<span class="line"><span style="color: #F286C4">alias</span><span style="color: #F6F6F4"> brdcms</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">br db:drop db:create db:migrate db:seed</span><span style="color: #DEE492">&quot;</span></span>
<span class="line"><span style="color: #F286C4">alias</span><span style="color: #F6F6F4"> rcr</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">bin/rails cypress:run</span><span style="color: #DEE492">&quot;</span></span>
<span class="line"><span style="color: #F286C4">alias</span><span style="color: #F6F6F4"> rco</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">bin/rails cypress:open</span><span style="color: #DEE492">&quot;</span></span>
<span class="line"><span style="color: #F286C4">alias</span><span style="color: #F6F6F4"> resetdbtest</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">bin/rails db:drop db:create db:migrate RAILS_ENV=test</span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #F286C4">alias</span><span style="color: #F6F6F4"> resetdbdev</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">bin/rails db:drop db:create db:migrate RAILS_ENV=development</span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #F286C4">alias</span><span style="color: #F6F6F4"> brg</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">bin/rails generate</span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #F286C4">alias</span><span style="color: #F6F6F4"> brt</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">bin/rails test</span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #F286C4">alias</span><span style="color: #F6F6F4"> fd</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">foreman start -f Procfile.dev</span><span style="color: #DEE492">&quot;</span></span></code></pre></div>



<p class="wp-block-paragraph">Happy Coding!</p>
<p>The post <a href="https://blog.tomosia.com.vn/rails-console-command-made-easier/">Rails console command made easier</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/rails-console-command-made-easier/feed/</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
			</item>
		<item>
		<title>Ruby 3.0 đã chính thức hỗ trợ Pattern Matching</title>
		<link>https://blog.tomosia.com.vn/ruby-3-0-da-chinh-thuc-ho-tro-pattern-matching/</link>
					<comments>https://blog.tomosia.com.vn/ruby-3-0-da-chinh-thuc-ho-tro-pattern-matching/#comments</comments>
		
		<dc:creator><![CDATA[Minh Tang]]></dc:creator>
		<pubDate>Mon, 11 Dec 2023 02:25:03 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=2508</guid>

					<description><![CDATA[<p>Pattern Matching trong Ruby cho phép giải cấu trúc dữ liệu một cách ngắn gọn, giúp dễ dàng&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/ruby-3-0-da-chinh-thuc-ho-tro-pattern-matching/">Ruby 3.0 đã chính thức hỗ trợ Pattern Matching</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Pattern Matching trong Ruby cho phép giải cấu trúc dữ liệu một cách ngắn gọn, giúp dễ dàng gán giá trị cho các biến với cú pháp rõ ràng. Pattern matching là một tính năng đã được giới thiệu trong Ruby 2.7. Từ Ruby 3.0 trở đi, nó không còn là một tính năng thử nghiệm nữa và chúng ta có thể bắt đầu sử dụng nó một cách chính thức.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Warning Ruby 2.7: Pattern matching is experimental, and the behavior may change in future versions of Ruby!</p>
</blockquote>



<h2 id="pattern-matching-la-gi" class="wp-block-heading">Pattern Matching là gì?</h2>



<p class="wp-block-paragraph">Pattern matching là một tính năng cho phép bạn so sánh và hiểu cấu trúc dữ liệu. Điều này được thực hiện bằng cách kiểm tra cách thông tin được tổ chức và gán các phần tương ứng cho các biến cục bộ để sử dụng sau này.</p>



<p class="wp-block-paragraph">Pattern Matching được hỗ trợ thông qua cú pháp <strong>case / in</strong>. Quan trọng là không nhầm lẫn với <strong>case / when</strong> và không kết hợp chúng. Nếu không có sự phù hợp với bất kỳ biểu thức nào và không có định nghĩa <code>else</code>, thì một ngoại lệ <code>NoMatchingPatternError</code> sẽ được raise</p>



<pre class="wp-block-code"><code>case &lt;expression&gt;
in &lt;pattern1&gt;
  # ...
in &lt;pattern2&gt;
  # ...
else
  # ...
end
</code></pre>



<p class="wp-block-paragraph">Pattern có thể là:</p>



<ul class="wp-block-list">
<li><strong>Value</strong>: Any Ruby object (compared with the === operator, as in ‘when’).</li>



<li><strong>Array</strong>: Array pattern:&nbsp;<strong><code>[&lt;subpattern&gt;, &lt;subpattern&gt;, &lt;subpattern&gt;, &lt;subpattern&gt;, ...]</code></strong>.</li>



<li><strong>Find</strong>: Search pattern:&nbsp;<strong><code>[*variable, &lt;subpattern&gt;, &lt;subpattern&gt;, &lt;subpattern&gt;, &lt;subpattern&gt;, ..., *variable]</code></strong>.</li>



<li><strong>Hash</strong>: Hash pattern:&nbsp;<strong><code>{key: &lt;subpattern&gt;, key: &lt;subpattern&gt;, ...}</code></strong>.</li>



<li><strong>Alternative</strong>: Pattern combination with&nbsp;<strong><code>|</code></strong>&nbsp;(vertical bar).</li>



<li><strong>Variable capture</strong>:&nbsp;<strong><code>&lt;pattern&gt; =&gt; variable</code></strong>&nbsp;or&nbsp;<strong><code>variable</code></strong>.</li>
</ul>



<h2 id="dinh-nghia-pattern-matching" class="wp-block-heading">Định nghĩa Pattern Matching</h2>



<pre class="wp-block-code"><code># Define a method that uses pattern matching with case/in
def process_data(data)
  case data
  in { type: "number", value: Integer =&gt; num }
    puts "Received a number: #{num}"
  in { type: "string", value: String =&gt; str }
    puts "Received a string: #{str}"
  in { type: "array", value: Array =&gt; arr }
    puts "Received an array: #{arr}"
  in { type: "hash", value: Hash =&gt; hash }
    puts "Received a hash: #{hash}"
  else
    puts "Received something else."
  end
end

# Test the method with different data structures
process_data({ type: "number", value: 42 })               # Output: Received a number: 42
process_data({ type: "string", value: "Hello, Ruby!" })   # Output: Received a string: Hello, Ruby!
process_data({ type: "array", value: &#91;1, 2, 3] })         # Output: Received an array: &#91;1, 2, 3]
process_data({ type: "hash", value: { key: "value" } })   # Output: Received a hash: {:key=&gt;"value"}
process_data({ type: "unknown", value: "unknown data" })  # Output: Received something else.
</code></pre>



<h3 id="deconstruct-va-deconstruct_keys" class="wp-block-heading">Deconstruct và Deconstruct_keys</h3>



<p class="wp-block-paragraph">Đây là hai phương thức đặc biệt trong pattern matching: <code>deconstruct</code>, được gọi khi đánh giá trên một <strong>Array</strong>, và <code>deconstruct_keys</code> được gọi khi đánh giá trên một <strong>Hash</strong>. Hãy xem một ví dụ:</p>



<pre class="wp-block-code"><code>class Coordinates
  attr_accessor :x, :y

  def initialize(x, y)
    @x = x
    @y = y
  end

  def deconstruct
    &#91;@x, @y]
  end

  def deconstruct_key
    {x: @x, y: @y}
  end
end
</code></pre>



<p class="wp-block-paragraph">Khi một thể hiện của lớp Coordinate được đánh giá trên một Array</p>



<pre class="wp-block-code"><code>c = Coordinates.new(32,50)

case c
in &#91;a,b]
  p a #=&gt; 32
  p b #=&gt; 50
end
</code></pre>



<p class="wp-block-paragraph">Khi một thể hiện của lớp Coordinate được đánh giá trên một Hash</p>



<pre class="wp-block-code"><code>case c
in {x:, y:}
  p x #=&gt; 32
  p y #=&gt; 50
end
</code></pre>



<p class="wp-block-paragraph">Nếu class không có 2 methods trên thì sẽ báo lỗi</p>



<pre class="wp-block-code"><code>#&lt;Coordinate:0x000000010d27fb10 @x=32, @y=50&gt;: #&lt;Coordinate:0x000000010d27fb10 @x=32, @y=50&gt; does not respond to #deconstruct (NoMatchingPatternError)
</code></pre>



<p class="wp-block-paragraph">Tham khảo thêm tại: <a href="https://docs.ruby-lang.org/en/master/syntax/pattern_matching_rdoc.html">https://docs.ruby-lang.org/en/master/syntax/pattern_matching_rdoc.html</a></p>
<p>The post <a href="https://blog.tomosia.com.vn/ruby-3-0-da-chinh-thuc-ho-tro-pattern-matching/">Ruby 3.0 đã chính thức hỗ trợ Pattern Matching</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/ruby-3-0-da-chinh-thuc-ho-tro-pattern-matching/feed/</wfw:commentRss>
			<slash:comments>16</slash:comments>
		
		
			</item>
		<item>
		<title>Debug trong Ruby mà không cần dùng thư viện</title>
		<link>https://blog.tomosia.com.vn/debug-trong-ruby-ma-khong-can-dung-thu-vien/</link>
					<comments>https://blog.tomosia.com.vn/debug-trong-ruby-ma-khong-can-dung-thu-vien/#comments</comments>
		
		<dc:creator><![CDATA[Minh Tang]]></dc:creator>
		<pubDate>Wed, 22 Nov 2023 01:44:30 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=1949</guid>

					<description><![CDATA[<p>Hướng dẫn debug không cần sử dụng thêm thư viện bên ngoài</p>
<p>The post <a href="https://blog.tomosia.com.vn/debug-trong-ruby-ma-khong-can-dung-thu-vien/">Debug trong Ruby mà không cần dùng thư viện</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Thông thường chúng ta muốn debug trong ruby thì hay sử dụng các gem pry, debugger, byebug. Nhược điểm là phải sử dụng thêm thư viện bên ngoài. Còn ở bài viết này mình sẽ chia sẻ thêm 1 cách mà không cần sử dụng thư viện bên ngoài mà vẫn có thể debug được.</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="# door.rb
class Door
  def initialize
    @open = false
    binding.irb
    puts &quot;Is the door open: #{@open}&quot;
  end
end

Door.new" 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"># door.rb</span></span>
<span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Door</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #F286C4">def</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">initialize</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #BF9EEE; font-style: italic">@open</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">false</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #97E1F1">binding</span><span style="color: #F6F6F4">.irb</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #97E1F1">puts</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">Is the door open: </span><span style="color: #F286C4">#{</span><span style="color: #BF9EEE; font-style: italic">@open</span><span style="color: #F286C4">}</span><span style="color: #DEE492">&quot;</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #F286C4">end</span></span>
<span class="line"><span style="color: #F286C4">end</span></span>
<span class="line"></span>
<span class="line"><span style="color: #97E1F1; font-style: italic">Door</span><span style="color: #F6F6F4">.</span><span style="color: #F286C4">new</span></span></code></pre></div>



<p class="wp-block-paragraph">Kết quả:</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="Documentos/scripts/ruby via 💎 v3.2.2
❯ ruby door.rb

From: door.rb @ line 4 :

    1: class Door
    2:   def initialize
    3:     @open = false
 =&gt; 4:     binding.irb
    5:     puts &quot;Is the door open: #{@open}&quot;
    6:   end
    7: end
    8:
    9: Door.new

irb(#&lt;Door:0x00007fa9a0f367a8&gt;):001&gt; @open
=&gt; false
irb(#&lt;Door:0x00007fa9a0f367a8&gt;):002&gt; @open=true
=&gt; true
irb(#&lt;Door:0x00007fa9a0f367a8&gt;):003&gt; exit
Is the door open: true" 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: #BF9EEE">Documentos</span><span style="color: #F286C4">/</span><span style="color: #F6F6F4">scripts</span><span style="color: #F286C4">/</span><span style="color: #F6F6F4">ruby via 💎 v3.</span><span style="color: #BF9EEE">2.2</span></span>
<span class="line"><span style="color: #F6F6F4">❯ ruby door.rb</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">From</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> door.rb @ line </span><span style="color: #BF9EEE">4</span><span style="color: #F6F6F4"> :</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #BF9EEE">1</span><span style="color: #F6F6F4">: </span><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">Door</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #BF9EEE">2</span><span style="color: #F6F6F4">:   </span><span style="color: #F286C4">def</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">initialize</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #BF9EEE">3</span><span style="color: #F6F6F4">:     </span><span style="color: #BF9EEE; font-style: italic">@open</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">false</span></span>
<span class="line"><span style="color: #F6F6F4"> </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">4</span><span style="color: #F6F6F4">:     </span><span style="color: #97E1F1">binding</span><span style="color: #F6F6F4">.irb</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #BF9EEE">5</span><span style="color: #F6F6F4">:     </span><span style="color: #97E1F1">puts</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">Is the door open: </span><span style="color: #F286C4">#{</span><span style="color: #BF9EEE; font-style: italic">@open</span><span style="color: #F286C4">}</span><span style="color: #DEE492">&quot;</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #BF9EEE">6</span><span style="color: #F6F6F4">:   </span><span style="color: #F286C4">end</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #BF9EEE">7</span><span style="color: #F6F6F4">: </span><span style="color: #F286C4">end</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #BF9EEE">8</span><span style="color: #F6F6F4">:</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #BF9EEE">9</span><span style="color: #F6F6F4">: </span><span style="color: #97E1F1; font-style: italic">Door</span><span style="color: #F6F6F4">.</span><span style="color: #F286C4">new</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">irb(</span><span style="color: #7B7F8B">#&lt;Door:0x00007fa9a0f367a8&gt;):001&gt; @open</span></span>
<span class="line"><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">false</span></span>
<span class="line"><span style="color: #F6F6F4">irb(</span><span style="color: #7B7F8B">#&lt;Door:0x00007fa9a0f367a8&gt;):002&gt; @open=true</span></span>
<span class="line"><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">true</span></span>
<span class="line"><span style="color: #F6F6F4">irb(</span><span style="color: #7B7F8B">#&lt;Door:0x00007fa9a0f367a8&gt;):003&gt; exit</span></span>
<span class="line"><span style="color: #BF9EEE">Is</span><span style="color: #F6F6F4"> the door open</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">true</span></span></code></pre></div>



<p class="wp-block-paragraph">Happy coding! =]]z</p>
<p>The post <a href="https://blog.tomosia.com.vn/debug-trong-ruby-ma-khong-can-dung-thu-vien/">Debug trong Ruby mà không cần dùng thư viện</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/debug-trong-ruby-ma-khong-can-dung-thu-vien/feed/</wfw:commentRss>
			<slash:comments>14</slash:comments>
		
		
			</item>
		<item>
		<title>Những tính năng mới trong GPT-4 Turbo &#8211; Devday OpenAI</title>
		<link>https://blog.tomosia.com.vn/nhung-tinh-nang-moi-trong-gpt-4-turbo-devday-openai/</link>
					<comments>https://blog.tomosia.com.vn/nhung-tinh-nang-moi-trong-gpt-4-turbo-devday-openai/#comments</comments>
		
		<dc:creator><![CDATA[Minh Tang]]></dc:creator>
		<pubDate>Wed, 08 Nov 2023 18:15:37 +0000</pubDate>
				<category><![CDATA[OpenAI]]></category>
		<category><![CDATA[chatgpt]]></category>
		<category><![CDATA[openai]]></category>
		<category><![CDATA[Devday]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=1779</guid>

					<description><![CDATA[<p>Vào ngày 06/11/2023 vừa qua, tổng giám đốc của OpenAI Sam Altman đã công bố nhiều tính năng&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/nhung-tinh-nang-moi-trong-gpt-4-turbo-devday-openai/">Những tính năng mới trong GPT-4 Turbo &#8211; Devday OpenAI</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Vào ngày 06/11/2023 vừa qua, tổng giám đốc của OpenAI Sam Altman đã công bố nhiều tính năng và sự thay đổi của OpenAI, mình sẽ điểm qua một số ý chính trong buổi Dev Day như sau:</p>



<h3 id="1-nang-cap-mo-hinh-gpt-4-len-gpt-4-turbo" class="wp-block-heading">1. Nâng cấp mô hình GPT-4 lên GPT-4 Turbo</h3>



<ul class="wp-block-list">
<li>Đây là một phiên bản nâng cấp của mô hình GPT-4, với input đầu vào là 128K (128.000) ký tự (tương đương hơn 300 trang sách, trước đó chỉ có 32K (32.000) ký tự). Hãy tưởng tượng khả năng duy trì bối cảnh của một cuốn sách dày cộm chỉ trong một lần nhận dữ liệu. Giống như việc mô hình này có thể &#8220;đọc&#8221; lên đến 300 trang sách trong một lời gợi ý. Ví dụ: Bạn có thể đặt câu hỏi phức tạp về lịch sử và mô hình sẽ có khả năng trả lời mà không cần giới hạn bởi việc chia thành nhiều đoạn.</li>



<li>Sự hiểu biết về các sự kiện trên thế giới được cập nhập cho đến tháng 4 năm 2023. Đây không chỉ là một bước tiến trong công nghệ AI mà còn là cầu nối cho các nhà phát triển đến với những khả năng mới.</li>



<li>GPT-4 Turbo giá rẻ hơn gấp 3 lần cho các token input đầu vào và rẻ hơn 2 lần cho các token output đầu ra so với GPT-4</li>



<li>Hiện tại GPT-4 Turbo vẫn chưa được chính thức, nhưng trong vài tuần tới sẽ phát hành. Hiện tại chúng ta có thể sử dụng model <code>gpt-4-1106-preview</code> để trải nghiệm</li>
</ul>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="572" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.10.34-1024x572.png" alt="" class="wp-image-1780" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.10.34-1024x572.png 1024w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.10.34-300x168.png 300w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.10.34-768x429.png 768w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.10.34-1536x858.png 1536w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.10.34-380x212.png 380w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.10.34-800x447.png 800w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.10.34-1160x648.png 1160w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.10.34.png 1618w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h3 id="2-loai-bo-tinh-nang-function-thay-vao-do-la-function-calling" class="wp-block-heading">2. Loại bỏ tính năng function, thay vào đó là function-calling</h3>



<ul class="wp-block-list">
<li>Tính năng <code>functions</code> trước đây <a href="https://platform.openai.com/docs/api-reference/chat/create#chat-create-functions">đã bị loại bỏ</a> thay vào đó là tính năng <code>function-calling</code></li>



<li>Tính năng này theo mình thấy cực kỳ hữu ích. Để diễn giải thì có vẻ hơi khó hình dung, mình sẽ đưa ra một ví dụ như sau:
<ul class="wp-block-list">
<li>Ví dụ 1: Giả sử trong quá trình trò chuyện với ChatGPT nếu ta hỏi thời tiết hôm nay thế nào, nhiệt độ bao nhiêu, bây giờ là mấy giờ thì có lẻ ở version trước đây sẽ không làm được, vì kiến thức của nó không phải là realtime. Nhưng dựa vào <code>function-calling</code> thì khi ta nhập prompt vào thì nó sẽ xác định cần gọi đến function nào và tham số đầu vào cho phù hợp, từ đó ta sẽ trigger function và hiển thị kết quả cho người dùng</li>



<li>Ví dụ 2: Ở trong buổi DevDay <a href="https://www.youtube.com/live/U9mJuUkhUzk?si=AdeGrGMKlhKZpGK3&amp;t=2457">(Phút 41 &#8211; DevDay Keynote)</a>, họ đã dựa vào những khán giả tham dự và yêu cầu AI liệt kê ra 5 người ngẫu nhiên để tặng 500$. Thì lúc này tính năng <code>function-calling</code> sẽ giải quyết bài toán đưa ra câu lệnh Query và truyền vào function để thực thi truy vấn lấy ra 5 người ngẫu nhiên.</li>



<li>Ví dụ 3: Bạn củng có thể xem demo ở <a href="https://www.youtube.com/live/U9mJuUkhUzk?si=EQ71WNhVrfAlSohq&amp;t=2110">Phút 35 &#8211; DevDay Keynote</a> củng sẽ rất thú vị</li>
</ul>
</li>



<li>Tham khảo: <a href="https://platform.openai.com/docs/guides/function-calling">https://platform.openai.com/docs/guides/function-calling</a></li>
</ul>



<h3 id="3-cai-thien-response-format" class="wp-block-heading">3. Cải thiện response format</h3>



<ul class="wp-block-list">
<li>Sự cải thiện này cho phép ta có thể chỉ định định dạng trả về là JSON (new) hay là text. Với định dạng JSON thì khá hữu ích cho các Developers</li>



<li>Tham khảo: <a href="https://platform.openai.com/docs/guides/text-generation/json-mode">https://platform.openai.com/docs/guides/text-generation/json-mode</a></li>
</ul>



<h3 id="4-reproducible-outputs-and-log-probabilities" class="wp-block-heading">4. Reproducible outputs and log probabilities</h3>



<ul class="wp-block-list">
<li>Với tiêu đề trên thì dịch ra có nghĩa là “Kết quả tái sản xuất và xác suất nhật ký”, nghe có vẻ khó hiểu, mình còn không hiểu mình đang viết cái gì cơ mà =)) Nhưng đừng lo lắng, nghe có vẻ rườm rà vậy thôi chứ nó củng chẳng có gì ghê gớm lắm đâu. 😄&nbsp;Mình sẽ ví dụ như thế này cho anh em dễ hình dung</li>



<li>Ví dụ trước đây khi mình viết ứng dụng và gọi đến API completion và sau đó nhận kết quả từ OpenAI. Nhưng cái khó ở chỗ là củng cùng một prompt nhưng mà mỗi lần response trả về sẽ cho ra kết quả khác nhau =)) Vậy trong quá trình phát triển sản phẩm, với output như vậy thì làm sao viết Unit Test nhỉ =))</li>



<li>Bởi vì chúng ta không thể phán đoán được AI response về cái gì nên việc viết UnitTest sẽ trở nên khó khăn (có thể là không viết được). Cho nên ở lần release này đã họ đã tích hợp thêm tham số <code>seed</code> và <code>fingerprint</code> Với 2 tham số này sẽ cho ra kết quả giống nhau với cùng 1 prompt. Mình nói tới đây chắc là anh em củng đã hình dung được rồi nhỉ 😀</li>



<li>Tóm lại tính năng này phục vụ cho developers trong quá trình phát triển sản phẩm, kiểm tra tính đúng đắn của chương trình =))))</li>
</ul>



<h3 id="5-cap-nhap-gpt-3-5-turbo" class="wp-block-heading">5. Cập nhập GPT-3.5 Turbo</h3>



<ul class="wp-block-list">
<li>Ngoài GPT-4 Turbo, thì họ củng đã cập nhập cho GPT-3.5 vói 16K ký tự, và vẫn giống như tính năng bên GPT-4 Turbo ta vẫn có thể sử dụng với tính năng <code>function-calling</code> , định dạng <code>response_format</code></li>



<li>Chúng ta có thể truy cập mô hình mới này bằng cách gọi <code>gpt-3.5-turbo-1106</code> trong API. Các ứng dụng sử dụng tên <code>gpt-3.5-turbo</code> <em>sẽ tự động nâng cấp lên mô hình mới vào ngày 11 tháng 12.</em> <em>Các mô hình cũ sẽ tiếp tục được truy cập bằng cách chuyển <code>gpt-3.5-turbo-0613</code> trong API cho đến ngày 13 tháng 6 năm 2024.</em></li>
</ul>



<h3 id="6-gpt-4-turbo-vision" class="wp-block-heading">6. GPT-4 Turbo Vision</h3>



<ul class="wp-block-list">
<li>Anh em cứ hình dung đây chính là con mắt của GPT. Ở GPT-4 Turbo có thể nhận diện hình ảnh làm đầu vào. Nó sẽ hjoàn thiện cuộc trò chuyện, cho phép các ứng dụng phân tích chi tiết hình ảnh thế giới thực và đọc tài liệu có hình ảnh.</li>



<li>Ví dụ, BeMyEyes sử dụng công nghệ này để giúp người khiếm thị hoặc có thị lực kém trong các công việc hàng ngày như xác định một sản phẩm hoặc di chuyển trong cửa hàng.</li>



<li>Ta có thể truy cập tính năng này bằng cách sử dụng <code>gpt-4-vision-preview</code> trong API. Hiện tại tính năng này vẫn đang phát triển và chưa hoàn thiện. Giá cả phụ thuộc vào kích thước hình ảnh đầu vào. Ví dụ, một hình ảnh có kích thước 1080×1080 pixel cho GPT-4 Turbo có giá là $0.00765.</li>
</ul>



<p class="wp-block-paragraph"><strong>DALL·E 3</strong></p>



<ul class="wp-block-list">
<li>Chúng ta có thể tích hợp DALL·E 3, mà gần đây OpenAI đã ra mắt cho người dùng ChatGPT Plus và Enterprise thông qua API hình ảnh.</li>



<li>Các công ty như Snap, Coca-Cola và Shutterstock đã sử dụng DALL·E 3 để tạo ra hình ảnh và thiết kế một cách tự động cho khách hàng và chiến dịch của họ.</li>



<li>Tương tự như phiên bản trước của DALL·E, API này <strong>tích hợp kiểm duyệt tích hợp để giúp các nhà phát triển bảo vệ ứng dụng của họ khỏi việc sử dụng sai mục đích</strong>. Chúng tôi cung cấp các tùy chọn về định dạng và chất lượng khác nhau, với giá khởi điểm từ $0.04 cho mỗi hình ảnh được tạo ra</li>



<li>Tham khảo:
<ul class="wp-block-list">
<li><a href="https://platform.openai.com/docs/guides/moderation/overview">https://platform.openai.com/docs/guides/moderation/overview</a></li>



<li><a href="https://openai.com/policies/usage-policies">https://openai.com/policies/usage-policies</a></li>
</ul>
</li>
</ul>



<h3 id="7-text-to-speech-tts" class="wp-block-heading">7. <strong>Text-to-speech (TTS)</strong></h3>



<ul class="wp-block-list">
<li>Ở phiên bản trước đây đã có tính năng <code>Speech-to-text</code> (chuyển đổi giọng nói sang text) và bây giờ là chuyển đổi text sang giọng nói.</li>



<li>Đối với Speech-to-text thì đầu vào là file audio, hỗ trợ nhiều định dạng như <code>mp3</code>,&nbsp;<code>mp4</code>,&nbsp;<code>mpeg</code>,&nbsp;<code>mpga</code>,&nbsp;<code>m4a</code>,&nbsp;<code>wav</code>, và&nbsp;<code>webm</code> ****</li>



<li>Đối với Text-to-speech thì output đầu ra sẽ là <code>mp3</code>, <code>opus</code>, <code>aac</code>, <code>flac</code>
<ul class="wp-block-list">
<li>Opus: Dùng cho streaming độ trễ thấp.</li>



<li>AAC: Dùng cho nén âm thanh digital, phù hợp với YouTube, Android, iOS.</li>



<li>FLAC: Dùng cho nén âm thanh hạn chế mất mát thông tin, được ưa chuộng bởi những người yêu thích âm thanh để lưu trữ.</li>
</ul>
</li>



<li>Đôi với Text-to-speech thì ta có thể tạo ra giọng nói con người từ văn bản thông qua API. Mô hình TTS mới cung cấp 6 giọng đọc và 2 biến thể mô hình, <code>tts-1</code> và <code>tts-1-hd</code>. <code>tts</code> được tối ưu hóa cho các trường hợp sử dụng real-time và <code>tts-1-hd</code> được tối ưu hóa cho chất lượng. Giá cả bắt đầu từ $0.015 cho mỗi 1.000 ký tự đầu vào.</li>
</ul>



<h3 id="8-toi-uu-ve-mat-chi-phi" class="wp-block-heading">8. Tối ưu về mặt chi phí</h3>



<ul class="wp-block-list">
<li><strong>GPT-4 Turbo input tokens</strong> giảm giá 3 lần so với GPT-4 ở mức $0.01 và <strong>output tokens</strong> giảm giá 2 lần ở mức $0.03.</li>



<li><strong>GPT-3.5 Turbo input tokens</strong> giảm giá 3 lần so với mô hình 16K trước đó ở mức $0.001 và <strong>output tokens</strong> giảm giá 2 lần ở mức $0.002. Trước đây sử dụng GPT-3.5 Turbo 4K hưởng lợi từ việc giảm giá 33% cho <strong>input tokens</strong> ở mức $0.001. Những mức giá thấp chỉ áp dụng cho mô hình GPT-3.5 Turbo mới được giới thiệu.</li>



<li><strong>GPT-3.5 Turbo fine-tuning</strong> <strong>input tokens</strong> giảm giá 4 lần ở mức $0.003 và <strong>output tokens</strong> giảm giá 2.7 lần ở mức $0.006. Fine-tuning cũng hỗ trợ khung ngữ cảnh 16K với cùng giá như 4K với mô hình GPT-3.5 Turbo mới. Những mức giá mới này cũng áp dụng cho các mô hình gpt-3.5-turbo-0613.</li>
</ul>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="763" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/11/pricing-1024x763.png" alt="" class="wp-image-1789" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/11/pricing-1024x763.png 1024w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/pricing-300x225.png 300w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/pricing-768x572.png 768w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/pricing-380x283.png 380w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/pricing-800x596.png 800w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/pricing-1160x864.png 1160w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/pricing.png 1474w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="516" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.15.26-1024x516.png" alt="" class="wp-image-1781" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.15.26-1024x516.png 1024w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.15.26-300x151.png 300w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.15.26-768x387.png 768w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.15.26-1536x774.png 1536w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.15.26-380x191.png 380w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.15.26-800x403.png 800w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.15.26-1160x584.png 1160w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.15.26.png 1846w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h3 id="9-cam-ket-bao-ve-nguoi-dung" class="wp-block-heading">9. Cam kết bảo vệ người dùng</h3>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="563" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.13.20-1024x563.png" alt="" class="wp-image-1782" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.13.20-1024x563.png 1024w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.13.20-300x165.png 300w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.13.20-768x422.png 768w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.13.20-1536x844.png 1536w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.13.20-380x209.png 380w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.13.20-800x440.png 800w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.13.20-1160x638.png 1160w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/Screenshot-2023-11-08-at-13.13.20.png 1572w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h3 id="10-whisper-v3" class="wp-block-heading">10. Whisper v3</h3>



<ul class="wp-block-list">
<li>Tính năng này hiện đang trong quá trình phát triển. Cơ bản nó sẽ tự nhận diện giọng nói trên nhiều ngôn ngữ</li>



<li>Tham khảo mã nguồn mở: <a href="https://github.com/openai/whisper">https://github.com/openai/whisper</a></li>
</ul>



<h3 id="11-assistants-api-retrieval-and-code-interpreter" class="wp-block-heading">11. <strong>Assistants API, Retrieval, and Code Interpreter</strong></h3>



<p class="wp-block-paragraph">Đúng ra mình sẽ nói tính năng này từ đầu, nhưng cơ bản mình củng chưa sử dụng nên củng không giải thích được gì thêm, hiện tại nó củng đang ở phiên bản BETA, các bạn tạm đọc bản dịch từ ChatGPT nhé =))</p>



<ul class="wp-block-list">
<li>Assistants API, Retrieval, and Code Interpreter là các tính năng mới của GPT, một nền tảng AI cho phép bạn xây dựng các ứng dụng trợ lý AI có mục tiêu và có thể gọi các mô hình và công cụ để thực hiện các nhiệm vụ. Các tính năng này là:</li>
</ul>



<ul class="wp-block-list">
<li><strong>Assistants API</strong>: là một API mới giúp bạn tạo ra các trợ lý AI có thể hiểu và trả lời các câu hỏi và yêu cầu của người dùng bằng ngôn ngữ tự nhiên, và có thể sử dụng các mô hình và công cụ khác nhau để thực hiện các nhiệm vụ cụ thể. Ví dụ, bạn có thể xây dựng một trợ lý AI để phân tích dữ liệu, lập trình, lên kế hoạch du lịch, tạo âm nhạc, vẽ tranh, v.v.</li>
</ul>



<ul class="wp-block-list">
<li><strong>Retrieval</strong>: là một công cụ mới cho phép trợ lý AI của bạn truy xuất kiến thức từ các nguồn dữ liệu bên ngoài mô hình của bạn, chẳng hạn như dữ liệu lĩnh vực độc quyền, thông tin sản phẩm hoặc tài liệu do người dùng cung cấp. Điều này có nghĩa là bạn không cần phải tính toán và lưu trữ các embedding cho các tài liệu của bạn, hoặc thực hiện các thuật toán phân đoạn và tìm kiếm. Trợ lý AI của bạn sẽ tự động chọn kỹ thuật truy xuất phù hợp nhất dựa trên kinh nghiệm của chúng tôi trong việc xây dựng truy xuất kiến thức trong ChatGPT.</li>
</ul>



<ul class="wp-block-list">
<li><strong>Code Interpreter</strong>: là một công cụ mới cho phép trợ lý AI của bạn viết và chạy mã Python trong một môi trường thực thi cô lập, và có thể tạo đồ thị và biểu đồ, và xử lý các tệp có dữ liệu và định dạng khác nhau. Điều này cho phép trợ lý AI của bạn chạy mã lặp đi lặp lại để giải quyết các vấn đề mã hóa và toán học khó khăn, và hơn thế nữa.</li>
</ul>



<ul class="wp-block-list">
<li>Tóm lại, các tính năng mới của GPT giúp bạn tạo ra các trợ lý AI mạnh mẽ, linh hoạt và sáng tạo hơn. Bạn có thể tìm hiểu thêm về các tính năng này tại trang web chính thức của GPT.</li>
</ul>



<p class="wp-block-paragraph">Đây là demo của Code Interpreter: <a href="https://www.youtube.com/watch?v=3t7417CB-o8&amp;ab_channel=Howfinity">https://www.youtube.com/watch?v=3t7417CB-o8&amp;ab_channel=Howfinity</a></p>



<h3 id="loi-ket" class="wp-block-heading">Lời kết</h3>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="683" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/11/chatgpt-reasoning-ai-neurosicence-1024x683.webp" alt="" class="wp-image-1785" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/11/chatgpt-reasoning-ai-neurosicence-1024x683.webp 1024w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/chatgpt-reasoning-ai-neurosicence-300x200.webp 300w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/chatgpt-reasoning-ai-neurosicence-768x512.webp 768w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/chatgpt-reasoning-ai-neurosicence-380x253.webp 380w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/chatgpt-reasoning-ai-neurosicence-800x533.webp 800w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/chatgpt-reasoning-ai-neurosicence-1160x773.webp 1160w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/chatgpt-reasoning-ai-neurosicence.webp 1344w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">Với những tính năng mà GPT-4 Turbo mang lại quả thật là khủng khiếp. Anh em thử hình dung con người chúng ta sẽ có bộ não để suy nghĩ, con mắt đề nhìn sự vật, lỗ tai để lắng nghe, cái miệng để nói. Vậy thử đối chiếu xem các tính năng trên thì GPT đã đáp ứng đủ chưa.</p>



<ul class="wp-block-list">
<li>Con mắt (GPT-4 Vision)</li>



<li>Lỗ tai (Speech to text)</li>



<li>Cái miệng (Text to speech)</li>



<li>Bộ não (Completion &amp; Chat Completion)</li>
</ul>



<p class="wp-block-paragraph">Mình nghĩ một ngày nào đó không xa AI sẽ thực sự thay thế con người, như ở các bộ film hollywood về các dòng phim viễn tưởng, những gì ta xem và nghĩ sẽ khó có thể xảy ra trong thực tế, nhưng có lẻ một thời gian nửa GPT sẽ làm được tất cả, có khi thay thế con người củng có =)) Bởi vậy từ bây giờ chúng ta cố gắn trau dồi kiến thức, phải học hỏi và tạo ra sự khác biệt mà AI không làm được.</p>



<p class="wp-block-paragraph"><em>Thôi sợ quá đắp mền đi ngủ đây ae nhé =)))</em></p>



<p class="wp-block-paragraph">À mà khoan còn một ý này nửa =)) Ngoài ra, GPT Marketplace sẽ sớm mở cửa, tạo điều kiện cho các nhà phát triển không chỉ chia sẻ mà còn kiếm lợi nhuận từ các ứng dụng của mình. Kiểu giống như shopify, viết theme và đăng lên để bán thì ở GPT ta có thể tạo ra những ứng dụng để bán. Với những cập nhật này, hứa hẹn sẽ là một cuộc đua không ngừng nghỉ cho các nhà phát triển =))</p>
<p>The post <a href="https://blog.tomosia.com.vn/nhung-tinh-nang-moi-trong-gpt-4-turbo-devday-openai/">Những tính năng mới trong GPT-4 Turbo &#8211; Devday OpenAI</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/nhung-tinh-nang-moi-trong-gpt-4-turbo-devday-openai/feed/</wfw:commentRss>
			<slash:comments>13</slash:comments>
		
		
			</item>
		<item>
		<title>Nâng bao nhiêu pool connect database là phù hợp</title>
		<link>https://blog.tomosia.com.vn/nang-bao-nhieu-pool-connect-database-la-phu-hop/</link>
					<comments>https://blog.tomosia.com.vn/nang-bao-nhieu-pool-connect-database-la-phu-hop/#comments</comments>
		
		<dc:creator><![CDATA[Minh Tang]]></dc:creator>
		<pubDate>Tue, 07 Nov 2023 16:33:24 +0000</pubDate>
				<category><![CDATA[Kinh nghiệm]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Rails]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=1768</guid>

					<description><![CDATA[<p>Trong bài viết này chúng ta sẽ tìm hiểu về sự quan trọng của việc tối ưu hóa kết nối database và tìm cách đảm bảo rằng bạn đang sử dụng số lượng pool kết nối đúng đắn, tiết kiệm tài nguyên và đảm bảo hiệu suất hệ thống.</p>
<p>The post <a href="https://blog.tomosia.com.vn/nang-bao-nhieu-pool-connect-database-la-phu-hop/">Nâng bao nhiêu pool connect database là phù hợp</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h3 id="1-max_connection-database-hien-tai-la-bao-nhieu" class="wp-block-heading">1. Max_connection database hiện tại là bao nhiêu?</h3>



<p class="wp-block-paragraph">Giả sử ta sử dụng Database MySQL AWS thuộc dòng db.t2.large (2CPU &#8211; 8GB RAM). Để biết số lượng max_connection có 2 cách:</p>



<ul class="wp-block-list">
<li>Cách 1: Thực hiện truy vấn&nbsp;<code>SHOW GLOBAL VARIABLES LIKE 'max_connections';</code></li>



<li>Cách 2: Dùng công thức <code>max_connections = DBInstanceClassMemory/12582880</code>
<ul class="wp-block-list">
<li>Ram 8G ⇒ 8000000000 bytes / 12582880 = 635 pools</li>
</ul>
</li>
</ul>



<h3 id="2-nang-bao-nhieu-pool-la-hop-ly" class="wp-block-heading">2. Nâng bao nhiêu pool là hợp lý?</h3>



<p class="wp-block-paragraph">Giả sử ta có 3 con servers. Mỗi server chạy 4 workers. Mỗi worker chạy 16 threads.</p>



<p class="wp-block-paragraph">Mỗi thread là 1 connection đến database.</p>



<p class="wp-block-paragraph">Suy ra ta có tổng số threads trên 1 server ⇒&nbsp;<code>16 threads * 4 workers = 64 pools/server</code></p>



<p class="wp-block-paragraph">Ta có 3 servers ⇒&nbsp;<code>64 pools * 3 servers = 192 pools</code>&nbsp;⇒ Số pool tổng cộng là 192 pools</p>



<p class="wp-block-paragraph"><strong>Cho nên chỉ số&nbsp;<code>max_connection</code>&nbsp;&gt;&nbsp;<code>tổng số pools</code></strong></p>



<p class="wp-block-paragraph">Với database ở trên thì sẽ đáp ứng được. Nếu DB của bạn yếu thì các bạn cần phải điều chỉnh lại số lượng threads cho phù hợp. Miễn sao khi tổng các server lại nó phải bé hơn số max_connection</p>



<p class="wp-block-paragraph"><strong>Lưu ý:</strong> Đó là ta mới tính cho những server đang golive, ngoài ra còn có những server khác như background chẳng hạn, hoặc khi ứng dụng được Scale-up server thì củng phải được tính vào. Tốt nhất là ta nên chừa số lượng còn lại ít nhất phải được 25 pools (Còn tuỳ vào thực tế server của bạn như thế nào mà tính cho hợp lý)</p>



<p class="wp-block-paragraph">Nếu server bạn mạnh, bạn dùng nhiều threads thì đồng nghĩa với việc bạn phải nâng Database lên cho phù hợp. Chứ không thể server mạnh mà Database yếu thì không thể đáp ứng được.</p>
<p>The post <a href="https://blog.tomosia.com.vn/nang-bao-nhieu-pool-connect-database-la-phu-hop/">Nâng bao nhiêu pool connect database là phù hợp</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/nang-bao-nhieu-pool-connect-database-la-phu-hop/feed/</wfw:commentRss>
			<slash:comments>10</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[Rails7.1]]></category>
		<category><![CDATA[Rails]]></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 class="wp-block-paragraph">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 class="wp-block-paragraph">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 class="wp-block-paragraph">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 class="wp-block-paragraph">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 class="wp-block-paragraph">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 class="wp-block-paragraph">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 class="wp-block-paragraph">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 class="wp-block-paragraph"><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 class="wp-block-paragraph">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 class="wp-block-paragraph">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 class="wp-block-paragraph">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 class="wp-block-paragraph"><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>12</slash:comments>
		
		
			</item>
		<item>
		<title>Cài đặt Rails 7 với Vite + Stimulus + Tailwind</title>
		<link>https://blog.tomosia.com.vn/cai-dat-rails-7-voi-vite-stimulus-tailwind/</link>
					<comments>https://blog.tomosia.com.vn/cai-dat-rails-7-voi-vite-stimulus-tailwind/#comments</comments>
		
		<dc:creator><![CDATA[Minh Tang]]></dc:creator>
		<pubDate>Thu, 12 Oct 2023 01:38:46 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Rails]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=1202</guid>

					<description><![CDATA[<p>Nếu bạn đang tìm kiếm một giải pháp phát triển web hiệu suất cao và tiện lợi, Vite sẽ là lựa chọn đáng xem xét. Còn với Rails 7, bạn sẽ phải cân nhắc xem tính năng importmap có đủ thuyết phục để bạn chuyển đổi không.</p>
<p>The post <a href="https://blog.tomosia.com.vn/cai-dat-rails-7-voi-vite-stimulus-tailwind/">Cài đặt Rails 7 với Vite + Stimulus + Tailwind</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><strong>Rails 7</strong> vừa chào đón sự xuất hiện của tính năng <code>importmap</code>, một tính năng đầy hứa hẹn giúp quản lý tài nguyên trên ứng dụng web dễ dàng hơn. Tuy nhiên Vite vẫn đang là một lựa chọn đáng chú ý trong cộng đồng phát triển web.</p>



<p class="wp-block-paragraph"><strong>Vite</strong> nổi bật với hai tính năng mà không ai có thể phủ nhận: <code>Instant Server Start</code> và <code>Lightning Fast HMR</code>.</p>



<ul class="wp-block-list">
<li><code>Instant Server Start</code> cho phép phục vụ tệp trên yêu cầu qua ESM, không cần đóng gói.</li>
</ul>



<ul class="wp-block-list">
<li><code>Lightning Fast HMR</code> là chức năng Hot Module Replacement (HMR) nhanh chóng</li>
</ul>



<p class="wp-block-paragraph">Điều đặc biệt là Vite sử dụng <code>esbuild</code>, một công cụ <code>pre-bundler</code> có tốc độ xử lý vượt trội, cùng với <code>rollup</code> để bundle mã nguồn. Kết hợp cả hai, sẽ tận dụng sức mạnh của chúng để cung cấp một trải nghiệm phát triển và triển khai web mạnh mẽ.</p>



<p class="wp-block-paragraph">Vậy nếu bạn đang tìm kiếm một giải pháp phát triển web hiệu suất cao và tiện lợi, Vite sẽ là lựa chọn đáng xem xét. Còn với Rails 7, bạn sẽ phải cân nhắc xem tính năng <code>importmap</code> có đủ thuyết phục để bạn chuyển đổi không.</p>



<h2 id="bat-dau-cai-dat-rails" class="wp-block-heading">Bắt Đầu: Cài Đặt Rails</h2>



<pre class="wp-block-code"><code>mkdir project_name &amp;&amp; cd project_name
rails new . --force --css=bootstrap --database=postgresql --minimal
rails db:create
rails db:migrate

// OR
echo "source '&lt;https://rubygems.org>'" > Gemfile
echo "gem 'rails', '7.1.0'" >> Gemfile
bundle install
bundle exec rails new . --force --css=bootstrap --database=postgresql --minimal
bin/rails db:create
bin/rails db:migrate
</code></pre>



<h2 id="buoc-1-cai-dat-vite" class="wp-block-heading">Bước 1: Cài Đặt Vite</h2>



<pre class="wp-block-code"><code>gem "vite_rails"
bundle install
bundle exec vite install

</code></pre>



<p class="wp-block-paragraph">Lệnh <code>vite install</code> sẽ tạo ra các tệp sau đây:</p>



<ul class="wp-block-list">
<li>Procfile cho môi trường phát triển để khởi chạy Rails và Vite:</li>
</ul>



<pre class="wp-block-code"><code>Procfile.dev
  vite: bin/vite dev
  web: bin/rails s</code></pre>



<ul class="wp-block-list">
<li>File entrypoint &#8211; Nơi chỉ chứa các lệnh imports</li>
</ul>



<pre class="wp-block-code"><code>app/javascript/entrypoints/</code></pre>



<ul class="wp-block-list">
<li>Tệp thực thi để bắt đầu vite:</li>
</ul>



<pre class="wp-block-code"><code>bin/vite</code></pre>



<ul class="wp-block-list">
<li>File cài đặt thư viện js</li>
</ul>



<pre class="wp-block-code"><code>package.json
package-lock.json</code></pre>



<ul class="wp-block-list">
<li>Cấu hình cho Vite cho ứng dụng:</li>
</ul>



<pre class="wp-block-code"><code>vite.config.ts
config/vite.json</code></pre>



<ul class="wp-block-list">
<li>Đặt cấu hình cho Vite:</li>
</ul>



<pre class="wp-block-code"><code># vite.config.ts

import { defineConfig } from 'vite'
import RubyPlugin from 'vite-plugin-ruby'
import FullReload from "vite-plugin-full-reload";

export default defineConfig({
  clearScreen: false,
  plugins: &#91;
    RubyPlugin(),
    FullReload(&#91;"config/routes.rb", "app/views/**/*"], { delay: 200 })
  ],
  root: "./app/assets",
  build: {
    manifest: true,
    rollupOptions: {
      input: "/app/javascript/entrypoints/application.js"
    }
  }
})</code></pre>



<p class="wp-block-paragraph">Vite cũng đi kèm với tính năng <code>auto build</code> . Vite-rails sẽ tự động phát hiện tùy chọn <code>"autoBuild": true</code> trong <code>vite.json</code>. Nếu có bất kỳ mã nào thay đổi trong thư mục được chỉ định trong <code>sourceCodeDir</code> và <code>watchAdditionalPaths</code>, nó sẽ tự động kích hoạt quá trình build tài nguyên</p>



<pre class="wp-block-code"><code># vite.json

{
  "all": {
    "sourceCodeDir": "app/javascript",
    "watchAdditionalPaths": &#91;]
  },
  "development": {
    "autoBuild": true,
    "publicOutputDir": "vite-dev",
    "port": 3036
  },
  "test": {
    "autoBuild": true,
    "publicOutputDir": "vite-test",
    "port": 3037
  }
}

</code></pre>



<p class="wp-block-paragraph">Vite xây dựng các tài nguyên và lưu trữ chúng trong <code>public/vite-dev</code> với các tệp CSS và JS được compile. Tệp <code>manifest.json</code> bao gồm các tệp CSS và JS cùng với tài nguyên từ <code>manifest-assets.json</code>.</p>



<pre class="wp-block-code"><code>Building with Vite ⚡️
vite v4.3.9 building for development...
transforming...

✓ 7 modules transformed.

rendering chunks...
computing gzip size...
../../public/vite-dev/manifest-assets.json              0.00 kB │ gzip:  0.02 kB
../../public/vite-dev/manifest.json                     0.30 kB │ gzip:  0.14 kB
../../public/vite-dev/assets/application-23aabef0.css   9.26 kB │ gzip:  2.39 kB
../../public/vite-dev/assets/application-cda856d1.js   43.44 kB │ gzip: 10.95 kB
✓ built in 481ms
Build with Vite complete: /Users/projects/app/public/vite-dev

</code></pre>



<p class="wp-block-paragraph">Bây giờ, sau khi khởi động lại Rails, bạn sẽ thấy những dòng thông báo này trên console của trình duyệt:</p>



<pre class="wp-block-code"><code>Vite ⚡️ Ruby
Visit the guide for more information: &lt;https://vite-ruby.netlify.app/guide/rails>

</code></pre>



<p class="wp-block-paragraph">Tất cả đã sẵn sàng để bạn viết chức năng JavaScript cho ứng dụng với Vite! 😃</p>



<h2 id="buoc-2-vite-stimulus" class="wp-block-heading">Bước 2: Vite + Stimulus</h2>



<p class="wp-block-paragraph">Vite có các plugin cho các framework như ReactJS và VueJS, cũng như một plugin cho framework Stimulus. Trong Rails 7, <code>gem 'stimulus-rails'</code> được cấu hình tự động. Vì vậy, để kết hợp Vite và Stimulus, hãy thực hiện các bước sau:</p>



<ul class="wp-block-list">
<li>Tạo các tệp Stimulus:</li>
</ul>



<pre class="wp-block-code"><code>gem 'stimulus-rails' # bỏ qua nếu đã được thêm bởi Rails
bundle install
rails stimulus:install # Tạo các tệp sau

</code></pre>



<ul class="wp-block-list">
<li>Rails đã thêm cài đặt cho Stimulus trong <code>app/javascript/controllers/application.js</code> và <code>app/javascript/controllers/index.js</code>. Vì chúng ta sẽ cấu hình Stimulus bằng Vite, bạn có thể bỏ qua tất cả các dòng từ hai tệp này.</li>



<li>Bỏ comment các import sau từ <code>app/javascript/application.js</code>:</li>
</ul>



<pre class="wp-block-code"><code>// import "@hotwired/turbo-rails"
// import "controllers"</code></pre>



<ul class="wp-block-list">
<li>Thêm hai plugin Vite mà bạn có thể sử dụng cho Stimulus:
<ul class="wp-block-list">
<li><code>stimulus-vite-helpers</code>: Cung cấp các helper để dễ dàng tải tất cả các controller Stimulus của bạn khi sử dụng Vite.js.</li>



<li><code>vite-plugin-stimulus-hmr</code>: HMR cho các controller Stimulus trong Vite.js.</li>
</ul>
</li>
</ul>



<pre class="wp-block-code"><code>yarn add -D @hotwired/stimulus
yarn add -D stimulus-vite-helpers
yarn add -D vite-plugin-stimulus-hmr</code></pre>



<p class="wp-block-paragraph">Câu lệnh trên sẽ thêm các phụ thuộc vào tệp <code>package.json</code>.</p>



<ul class="wp-block-list">
<li>Cấu hình Vite cho plugin HMR của Stimulus. Giờ đây, <code>vite.config.js</code> sẽ trông như sau:</li>
</ul>



<pre class="wp-block-code"><code>import { defineConfig } from 'vite'
import RubyPlugin from 'vite-plugin-ruby'
import FullReload from 'vite-plugin-full-reload';
import StimulusHMR from 'vite-plugin-stimulus-hmr';

export default defineConfig({
  clearScreen: false,
  plugins: &#91;
    RubyPlugin(),
    FullReload(&#91;"config/routes.rb", "app/views/**/*"], { delay: 200 }),
    StimulusHMR()
  ],
  root: "./app/assets",
  build: {
    manifest: true,
    rollupOptions: {
      input: "/app/javascript/entrypoints/application.js"
    }
  }
})</code></pre>



<ul class="wp-block-list">
<li>Thêm nội dung sau vào tệp <code>app/javascript/controllers/index.js</code>. Controllers Stimulus được đăng ký bằng cách sử dụng globEager của Vite và helper <code>registerControllers</code>.</li>
</ul>



<pre class="wp-block-code"><code>import { Application } from '@hotwired/stimulus'
import { registerControllers } from 'stimulus-vite-helpers'

const application = Application.start()
const controllers = import.meta.globEager('./**/*_controller.js')
registerControllers(application, controllers)</code></pre>



<ul class="wp-block-list">
<li>Import controller Stimulus vào tệp của Vite:</li>
</ul>



<p class="wp-block-paragraph">Thêm dòng sau vào <code>app/javascript/entrypoints/application.js</code>:</p>



<pre class="wp-block-code"><code>import '../controllers'</code></pre>



<ul class="wp-block-list">
<li>Để kiểm tra xem controller Stimulus &#8220;hello&#8221; hoạt động, thêm đoạn mã sau vào <code>app/views/layouts/application.html.erb</code>:</li>
</ul>



<pre class="wp-block-code"><code>&lt;div data-controller="hello">
  &lt;input data-hello-target="name" type="text">
  &lt;input data-hello-target="output" type="text">
  &lt;button data-action="click->hello#greet">Greet&lt;/button>
&lt;/div></code></pre>



<p class="wp-block-paragraph">Bạn đã sẵn sàng sử dụng Stimulus và Vite để phát triển ứng dụng của bạn!</p>



<h2 id="buoc-3-vite-tailwind" class="wp-block-heading">Bước 3: Vite + Tailwind</h2>



<ul class="wp-block-list">
<li>Sử dụng <code>yarn</code> để thêm Tailwind CSS và các gói cần thiết khác:</li>
</ul>



<pre class="wp-block-code"><code>yarn add -D tailwindcss @tailwindcss/forms @tailwindcss/typography @tailwindcss/aspect-ratio @tailwindcss/forms @tailwindcss/line-clamp autoprefixer
yarn add -D eslint prettier eslint-plugin-prettier eslint-config-prettier eslint-plugin-tailwindcss path</code></pre>



<ul class="wp-block-list">
<li>Tạo tệp cấu hình <code>tailwind.config.js</code> trong thư mục gốc của dự án:</li>
</ul>



<pre class="wp-block-code"><code>npx tailwindcss init</code></pre>



<p class="wp-block-paragraph">Thêm nội dung sau vào <code>tailwind.config.js</code>:</p>



<pre class="wp-block-code"><code>const colors = require('tailwindcss/colors')
const defaultTheme = require('tailwindcss/defaultTheme')

module.exports = {
  content: &#91;
    './app/helpers/**/*.rb',
    './app/assets/stylesheets/**/*.css',
    './app/views/**/*.{html,html.erb,erb}',
    './app/javascript/components/**/*.js',
  ],
  theme: {
    fontFamily: {
      'sans': &#91;"BlinkMacSystemFont", "Avenir Next", "Avenir",
        "Nimbus Sans L", "Roboto", "Noto Sans", "Segoe UI", "Arial", "Helvetica",
        "Helvetica Neue", "sans-serif"],
      'mono': &#91;"Consolas", "Menlo", "Monaco", "Andale Mono", "Ubuntu Mono", "monospace"]
    },
    extend: {},
  },
  corePlugins: {
    aspectRatio: false,
  },
  plugins: &#91;
    require('@tailwindcss/typography'),
    require('@tailwindcss/forms'),
    require('@tailwindcss/aspect-ratio'),
    require('@tailwindcss/line-clamp'),
  ],
}</code></pre>



<ul class="wp-block-list">
<li>Thay nội dung tệp <code>app/assets/stylesheets/application.css</code> bằng:</li>
</ul>



<pre class="wp-block-code"><code>@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";</code></pre>



<ul class="wp-block-list">
<li>Tạo tệp <code>application.css</code> trong thư mục <code>app/javascript/entrypoints/</code> và nhập các tệp stylesheet:</li>
</ul>



<pre class="wp-block-code"><code>@import "../../assets/stylesheets/application.css";</code></pre>



<ul class="wp-block-list">
<li>Tạo tệp cấu hình <code>postcss.config.js</code> trong thư mục gốc của dự án:</li>
</ul>



<pre class="wp-block-code"><code>touch postcss.config.js</code></pre>



<p class="wp-block-paragraph">Thêm nội dung sau vào <code>postcss.config.js</code>:</p>



<pre class="wp-block-code"><code>module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}</code></pre>



<ul class="wp-block-list">
<li>Trong <code>app/views/layouts/application.html.erb</code>, sử dụng các thẻ <code>vite_client_tag</code>, <code>vite_stylesheet_tag</code> và <code>vite_javascript_tag</code> thay vì các thẻ JS và CSS mặc định:</li>
</ul>



<pre class="wp-block-code"><code>&lt;%= csrf_meta_tags %>
&lt;%= csp_meta_tag %>

&lt;%= vite_client_tag %>
&lt;%= vite_stylesheet_tag 'application', data: { "turbo-track": "reload" } %>
&lt;%= vite_javascript_tag 'application' %></code></pre>



<ul class="wp-block-list">
<li>Hãy chắc chắn rằng các tài nguyên được biên dịch bằng cách xem F12 trình duyệt</li>
</ul>



<pre class="wp-block-code"><code>&lt;link rel="stylesheet" href="/vite-dev/assets/application-23aabef0.css" data-turbo-track="reload">
&lt;script src="/vite-dev/assets/application-cda856d1.js" crossorigin="anonymous" type="module">&lt;/script></code></pre>



<ul class="wp-block-list">
<li>Nếu cần, bạn có thể khởi chạy máy chủ Vite để áp dụng các kiểu Tailwind:</li>
</ul>



<pre class="wp-block-code"><code>bin/vite dev -clobber</code></pre>



<p class="wp-block-paragraph">Bạn đã sẵn sàng để viết mã JS và CSS cho ứng dụng của mình và để Vite đóng gói các tài nguyên này! 😄</p>



<p class="wp-block-paragraph"><em><a href="https://sasikala-r.medium.com/rails-7-with-vite-stimulus-tailwind-c3ecf2191ea9" data-type="link" data-id="https://sasikala-r.medium.com/rails-7-with-vite-stimulus-tailwind-c3ecf2191ea9">Nguồn tại Medium</a></em></p>
<p>The post <a href="https://blog.tomosia.com.vn/cai-dat-rails-7-voi-vite-stimulus-tailwind/">Cài đặt Rails 7 với Vite + Stimulus + Tailwind</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/cai-dat-rails-7-voi-vite-stimulus-tailwind/feed/</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
			</item>
	</channel>
</rss>
