{"id":1402,"date":"2025-03-24T08:52:16","date_gmt":"2025-03-23T23:52:16","guid":{"rendered":"https:\/\/dexall.co.jp\/articles\/?p=1402"},"modified":"2025-03-24T08:52:16","modified_gmt":"2025-03-23T23:52:16","slug":"%e3%80%90%e4%bf%9d%e5%ae%88%e6%80%a7%e6%8a%9c%e7%be%a4%e3%80%91ruby-on-rails-enum%e3%81%ae%e5%ae%8c%e5%85%a8%e3%82%ac%e3%82%a4%e3%83%89%ef%bc%9a%e5%9f%ba%e7%a4%8e%e3%81%8b%e3%82%89%e5%ae%9f%e8%b7%b5","status":"publish","type":"post","link":"https:\/\/dexall.co.jp\/articles\/?p=1402","title":{"rendered":"\u3010\u4fdd\u5b88\u6027\u629c\u7fa4\u3011Ruby on Rails enum\u306e\u5b8c\u5168\u30ac\u30a4\u30c9\uff1a\u57fa\u790e\u304b\u3089\u5b9f\u8df5\u7684\u306a\u6d3b\u7528\u307e\u3067\u89e3\u8aac"},"content":{"rendered":"\n<div class=\"toc\"><br \/>\n<b>Warning<\/b>:  Undefined array key \"is_admin\" in <b>\/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>116<\/b><br \/>\n<br \/>\n<b>Warning<\/b>:  Undefined array key \"is_category_top\" in <b>\/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>121<\/b><br \/>\n<br \/>\n<b>Warning<\/b>:  Undefined array key \"is_top\" in <b>\/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>128<\/b><br \/>\n    <div id=\"toc_container\" class=\"sgb-toc--bullets js-smooth-scroll\" data-dialog-title=\"\u76ee\u6b21\">\n      <p class=\"toc_title\">\u76ee\u6b21 <\/p>\n      <ul class=\"toc_list\">  <li class=\"first\">    <a href=\"#i-0\">Ruby on Rails enum\u3068\u306f\uff1a\u57fa\u790e\u304b\u3089\u7406\u89e3\u3059\u308b<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-1\">enum\u304c\u89e3\u6c7a\u3059\u308b3\u3064\u306e\u8ab2\u984c<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-2\">enum\u306e\u5229\u70b9\u3068\u5f93\u6765\u5b9f\u88c5\u3068\u306e\u6bd4\u8f03<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-3\">enum\u306e\u57fa\u672c\u7684\u306a\u5b9f\u88c5\u65b9\u6cd5<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-4\">\u30e2\u30c7\u30eb\u3067enum\u3092\u5b9a\u7fa9\u3059\u308b\u969b\u306e\u57fa\u672c\u69cb\u6587<\/a>      <\/li>      <li>        <a href=\"#i-5\">enum\u306b\u95a2\u9023\u3059\u308b\u4fbf\u5229\u306a\u30d8\u30eb\u30d1\u30fc\u30e1\u30bd\u30c3\u30c9<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-6\">\u65e5\u672c\u8a9e\u5316\u5bfe\u5fdc\u306e\u5b9f\u8df5\u30c6\u30af\u30cb\u30c3\u30af<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-7\">\u5b9f\u8df5\u7684\u306aenum\u30d1\u30bf\u30fc\u30f3\u6d3b\u7528<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-8\">\u30b9\u30c6\u30fc\u30bf\u30b9\u7ba1\u7406\u3067\u306e\u6d3b\u7528\u4f8b<\/a>      <\/li>      <li>        <a href=\"#i-9\">\u30d5\u30e9\u30b0\u7ba1\u7406\u3067\u306e\u6d3b\u7528\u4f8b<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-10\">\u6a29\u9650\u7ba1\u7406\u3067\u306e\u6d3b\u7528\u4f8b<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-11\">\u5217\u6319\u578b\u3092\u4f7f\u7528\u3059\u308b\u969b\u306e\u6ce8\u610f\u70b9\u3068\u5bfe\u7b56<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-12\">\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u6574\u5408\u6027\u3092\u78ba\u4fdd\u3059\u308b\u305f\u3081\u306e\u30de\u30a4\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u8a2d\u8a08<\/a>      <\/li>      <li>        <a href=\"#i-13\">enum\u306e\u5024\u3092\u5909\u66f4\u3059\u308b\u969b\u306e\u30ea\u30b9\u30af\u3068\u5bfe\u5fdc\u7b56<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-14\">\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u3067\u306e\u53d6\u308a\u6271\u3044\u65b9<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-15\">enum\u306e\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3068\u30e1\u30f3\u30c6\u30ca\u30f3\u30b9<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-16\">\u5927\u898f\u6a21\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306e\u5229\u7528\u6642\u306e\u6ce8\u610f\u70b9<\/a>      <\/li>      <li>        <a href=\"#i-17\">enum\u3092\u542b\u3080\u30e2\u30c7\u30eb\u306e\u30ea\u30d5\u30a1\u30af\u30bf\u30ea\u30f3\u30b0\u624b\u6cd5<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-18\">\u904b\u7528\u6642\u306e\u30c8\u30e9\u30d6\u30eb\u30b7\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0<\/a>      <\/li>    <\/ul>  <\/li>  <li class=\"last\">    <a href=\"#i-19\">\u767a\u5c55\u7684\u306aenum\u6d3b\u7528\u30c6\u30af\u30cb\u30c3\u30af<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-20\">\u30ab\u30b9\u30bf\u30e0\u30b9\u30b3\u30fc\u30d7\u3068\u306e\u7d44\u307f\u5408\u308f\u305b<\/a>      <\/li>      <li>        <a href=\"#i-21\">API\u30ec\u30b9\u30dd\u30f3\u30b9\u3067\u306e\u52b9\u679c\u7684\u306a\u6d3b\u7528\u65b9\u6cd5<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-22\">\u4ed6\u306egem\u3068\u306e\u9023\u643a\u6d3b\u7528\u4f8b<\/a>      <\/li>    <\/ul>  <\/li><\/ul>\n      <a href=\"#\" class=\"sgb-toc-button js-toc-button\" rel=\"nofollow\" data-open-dialog=\"true\"><i class=\"fa fa-list\"><\/i><span class=\"sgb-toc-button__text\">\u76ee\u6b21\u3078<\/span><\/a>\n    <\/div><\/div><h2 class=\"wp-block-heading\" id=\"i-0\">Ruby on Rails enum\u3068\u306f\uff1a\u57fa\u790e\u304b\u3089\u7406\u89e3\u3059\u308b<\/h2>\n\n\n\n<p>Active Record\u306b\u7d44\u307f\u8fbc\u307e\u308c\u305fenum\u306f\u3001\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u6574\u6570\u30ab\u30e9\u30e0\u3092\u4eba\u9593\u306b\u3068\u3063\u3066\u7406\u89e3\u3057\u3084\u3059\u3044\u6587\u5b57\u5217\u306b\u30de\u30c3\u30d4\u30f3\u30b0\u3059\u308b\u6a5f\u80fd\u3067\u3059\u3002\u3053\u306e\u6a5f\u80fd\u306b\u3088\u308a\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5185\u3067\u30b9\u30c6\u30fc\u30bf\u30b9\u3084\u72b6\u614b\u3092\u52b9\u7387\u7684\u306b\u7ba1\u7406\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-1\">enum\u304c\u89e3\u6c7a\u3059\u308b3\u3064\u306e\u8ab2\u984c<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30c7\u30fc\u30bf\u306e\u610f\u5473\u3065\u3051\u306e\u554f\u984c<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5f93\u6765\u306e\u5b9f\u88c5\u3067\u306f\u3001\u6574\u6570\u5024\u3060\u3051\u3067\u306f\u4f55\u3092\u8868\u3057\u3066\u3044\u308b\u306e\u304b\u7406\u89e3\u3057\u3065\u3089\u3044<\/li>\n\n\n\n<li>\u30b3\u30fc\u30c9\u4e2d\u3067\u6570\u5024\u306e\u610f\u5473\u3092\u7406\u89e3\u3059\u308b\u306e\u306b\u6642\u9593\u304c\u304b\u304b\u308b<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">   # \u5f93\u6765\u306e\u5b9f\u88c5\uff08\u5206\u304b\u308a\u3065\u3089\u3044\uff09\n   def status_name\n     case status\n     when 0 then '\u4e0b\u66f8\u304d'\n     when 1 then '\u516c\u958b\u6e08\u307f'\n     when 2 then '\u975e\u516c\u958b'\n     end\n   end<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u4fdd\u5b88\u6027\u3068\u30b3\u30fc\u30c9\u91cf\u306e\u554f\u984c<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30b9\u30c6\u30fc\u30bf\u30b9\u306e\u8ffd\u52a0\u30fb\u5909\u66f4\u6642\u306b\u591a\u304f\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u4fee\u6b63\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b<\/li>\n\n\n\n<li>\u5b9a\u6570\u5b9a\u7fa9\u3001\u30e1\u30bd\u30c3\u30c9\u5b9a\u7fa9\u3001\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u306a\u3069\u3001\u8907\u6570\u7b87\u6240\u306e\u5909\u66f4\u304c\u5fc5\u8981<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">   # \u5f93\u6765\u306e\u5b9f\u88c5\uff08\u4fdd\u5b88\u304c\u5927\u5909\uff09\n   class Article\n     STATUS_DRAFT = 0\n     STATUS_PUBLISHED = 1\n     STATUS_PRIVATE = 2\n\n     validates :status, inclusion: { in: [STATUS_DRAFT, STATUS_PUBLISHED, STATUS_PRIVATE] }\n\n     def published?\n       status == STATUS_PUBLISHED\n     end\n   end<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u30af\u30a8\u30ea\u3068\u30b9\u30b3\u30fc\u30d7\u306e\u554f\u984c<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u72b6\u614b\u306b\u57fa\u3065\u304f\u691c\u7d22\u3084\u7d5e\u308a\u8fbc\u307f\u306e\u305f\u3073\u306b\u6761\u4ef6\u3092\u66f8\u304f\u5fc5\u8981\u304c\u3042\u308b<\/li>\n\n\n\n<li>\u6761\u4ef6\u5f0f\u304c\u6563\u5728\u3057\u3001\u4e00\u8cab\u6027\u3092\u4fdd\u3064\u306e\u304c\u96e3\u3057\u3044<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-2\">enum\u306e\u5229\u70b9\u3068\u5f93\u6765\u5b9f\u88c5\u3068\u306e\u6bd4\u8f03<\/h3>\n\n\n<div id=\"id-73917608-b296-466e-838f-ad817a470da5\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u89b3\u70b9<\/th><th>enum\u4f7f\u7528\u6642<\/th><th>\u5f93\u6765\u5b9f\u88c5<\/th><\/tr><\/thead><tbody><tr><td>\u30b3\u30fc\u30c9\u91cf<\/td><td>\u5c11\u306a\u3044\uff081\u884c\u306e\u5b9a\u7fa9\u3067\u8907\u6570\u306e\u30e1\u30bd\u30c3\u30c9\u304c\u81ea\u52d5\u751f\u6210\uff09<\/td><td>\u591a\u3044\uff08\u5404\u30e1\u30bd\u30c3\u30c9\u3092\u500b\u5225\u306b\u5b9a\u7fa9\uff09<\/td><\/tr><tr><td>\u4fdd\u5b88\u6027<\/td><td>\u9ad8\u3044\uff08\u5b9a\u7fa9\u7b87\u6240\u304c\u4e00\u7b87\u6240\uff09<\/td><td>\u4f4e\u3044\uff08\u8907\u6570\u7b87\u6240\u306e\u5909\u66f4\u304c\u5fc5\u8981\uff09<\/td><\/tr><tr><td>\u53ef\u8aad\u6027<\/td><td>\u9ad8\u3044\uff08\u30b7\u30f3\u30dc\u30eb\u3067\u72b6\u614b\u3092\u8868\u73fe\uff09<\/td><td>\u4f4e\u3044\uff08\u6570\u5024\u306e\u610f\u5473\u304c\u5206\u304b\u308a\u3065\u3089\u3044\uff09<\/td><\/tr><tr><td>\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3<\/td><td>\u81ea\u52d5\u8a2d\u5b9a<\/td><td>\u624b\u52d5\u8a2d\u5b9a\u304c\u5fc5\u8981<\/td><\/tr><tr><td>\u30af\u30a8\u30ea\u5bfe\u5fdc<\/td><td>\u30b9\u30b3\u30fc\u30d7\u81ea\u52d5\u751f\u6210<\/td><td>\u624b\u52d5\u3067\u30b9\u30b3\u30fc\u30d7\u5b9a\u7fa9\u304c\u5fc5\u8981<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n<p>\u5b9f\u969b\u306eenum\u5b9f\u88c5\u4f8b:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Article &lt; ApplicationRecord\n  # \u305f\u3063\u305f1\u884c\u3067\u3053\u308c\u307e\u3067\u306e\u5b9f\u88c5\u3092\u30ab\u30d0\u30fc\n  enum status: { draft: 0, published: 1, private: 2 }\nend\n\n# \u751f\u6210\u3055\u308c\u308b\u30e1\u30bd\u30c3\u30c9\u4f8b\narticle.draft!       # \u30b9\u30c6\u30fc\u30bf\u30b9\u3092\u5909\u66f4\narticle.draft?       # \u72b6\u614b\u3092\u30c1\u30a7\u30c3\u30af\narticle.status       # \u73fe\u5728\u306e\u72b6\u614b\u3092\u53d6\u5f97\nArticle.draft        # scope\u3068\u3057\u3066\u4f7f\u7528\u53ef\u80fd<\/pre>\n\n\n\n<p>\u3053\u306e\u5b9f\u88c5\u306b\u3088\u308a\u3001\u4ee5\u4e0b\u306e\u30e1\u30ea\u30c3\u30c8\u304c\u5f97\u3089\u308c\u307e\u3059\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u76f4\u611f\u7684\u306a\u64cd\u4f5c<\/strong>: \u30b7\u30f3\u30dc\u30eb\u3092\u4f7f\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u30b3\u30fc\u30c9\u306e\u610f\u56f3\u304c\u660e\u78ba\u306b\u306a\u308a\u307e\u3059<\/li>\n\n\n\n<li><strong>\u30bf\u30a4\u30d7\u30bb\u30fc\u30d5<\/strong>: \u5b9a\u7fa9\u3055\u308c\u305f\u5024\u4ee5\u5916\u306f\u4f7f\u7528\u3067\u304d\u306a\u3044\u305f\u3081\u3001\u30d0\u30b0\u3092\u9632\u3052\u307e\u3059<\/li>\n\n\n\n<li><strong>\u81ea\u52d5\u751f\u6210<\/strong>: \u4fbf\u5229\u306a\u30d8\u30eb\u30d1\u30fc\u30e1\u30bd\u30c3\u30c9\u304c\u81ea\u52d5\u7684\u306b\u751f\u6210\u3055\u308c\u307e\u3059<\/li>\n\n\n\n<li><strong>\u52b9\u7387\u7684\u306a\u30af\u30a8\u30ea<\/strong>: \u30b9\u30b3\u30fc\u30d7\u304c\u81ea\u52d5\u751f\u6210\u3055\u308c\u3001\u691c\u7d22\u304c\u5bb9\u6613\u306b\u306a\u308a\u307e\u3059<\/li>\n<\/ul>\n\n\n\n<p>Rails 5.0\u4ee5\u964d\u3067\u306f\u3001enum\u306e\u6a5f\u80fd\u304c\u3055\u3089\u306b\u5f37\u5316\u3055\u308c\u3001\u8907\u6570\u306e\u30ab\u30e9\u30e0\u3067\u306e\u4f7f\u7528\u3084\u3001\u63a5\u982d\u8f9e\u306e\u8ffd\u52a0\u306a\u3069\u3082\u53ef\u80fd\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002\u3053\u308c\u306b\u3088\u308a\u3001\u3088\u308a\u67d4\u8edf\u306a\u72b6\u614b\u7ba1\u7406\u304c\u5b9f\u73fe\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u308a\u307e\u3057\u305f\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-3\">enum\u306e\u57fa\u672c\u7684\u306a\u5b9f\u88c5\u65b9\u6cd5<\/h2>\n\n\n\n<p>enum\u3092\u52b9\u679c\u7684\u306b\u6d3b\u7528\u3059\u308b\u306b\u306f\u3001\u57fa\u672c\u7684\u306a\u5b9f\u88c5\u65b9\u6cd5\u3092\u7406\u89e3\u3059\u308b\u3053\u3068\u304c\u91cd\u8981\u3067\u3059\u3002\u3053\u3053\u3067\u306f\u3001\u5b9f\u88c5\u306e\u57fa\u790e\u304b\u3089\u5fdc\u7528\u7684\u306a\u30c6\u30af\u30cb\u30c3\u30af\u307e\u3067\u3092\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-4\">\u30e2\u30c7\u30eb\u3067enum\u3092\u5b9a\u7fa9\u3059\u308b\u969b\u306e\u57fa\u672c\u69cb\u6587<\/h3>\n\n\n\n<p>enum\u306e\u5b9a\u7fa9\u65b9\u6cd5\u306b\u306f\u3001\u4e3b\u306b\u4ee5\u4e0b\u306e3\u3064\u306e\u30d1\u30bf\u30fc\u30f3\u304c\u3042\u308a\u307e\u3059\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u57fa\u672c\u7684\u306a\u5b9a\u7fa9\u65b9\u6cd5<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Post &lt; ApplicationRecord\n  # \u6700\u3082\u30b7\u30f3\u30d7\u30eb\u306a\u5b9a\u7fa9\n  enum status: [:draft, :published, :archived]\n\n  # \u660e\u793a\u7684\u306b\u5024\u3092\u6307\u5b9a\u3059\u308b\u5834\u5408\n  enum status: { draft: 0, published: 1, archived: 2 }\n\n  # \u6587\u5b57\u5217\u3092\u30ad\u30fc\u306b\u3059\u308b\u5834\u5408\uff08\u975e\u63a8\u5968\uff09\n  enum status: { \"\u4e0b\u66f8\u304d\" =&gt; 0, \"\u516c\u958b\u4e2d\" =&gt; 1, \"\u30a2\u30fc\u30ab\u30a4\u30d6\u6e08\" =&gt; 2 }\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u4f7f\u7528\u3057\u305f\u5b9a\u7fa9<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class User &lt; ApplicationRecord\n  # \u63a5\u982d\u8f9e\u3092\u3064\u3051\u308b\n  enum role: { general: 0, admin: 1, owner: 2 }, _prefix: true\n  # =&gt; user.role_admin?, user.role_general? \u306a\u3069\u304c\u751f\u6210\u3055\u308c\u308b\n\n  # \u63a5\u5c3e\u8f9e\u3092\u3064\u3051\u308b\n  enum status: { active: 0, inactive: 1 }, _suffix: true\n  # =&gt; user.active_status?, user.inactive_status? \u306a\u3069\u304c\u751f\u6210\u3055\u308c\u308b\n\n  # \u30ab\u30b9\u30bf\u30e0\u63a5\u982d\u8f9e\n  enum role: { general: 0, admin: 1 }, _prefix: :account\n  # =&gt; user.account_general?, user.account_admin? \u306a\u3069\u304c\u751f\u6210\u3055\u308c\u308b\nend<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u8907\u6570\u306eenum\u3092\u5b9a\u7fa9\u3059\u308b\u5834\u5408<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Article &lt; ApplicationRecord\n  # \u8907\u6570\u306eenum\u30921\u3064\u306e\u30e2\u30c7\u30eb\u3067\u5b9a\u7fa9\n  enum status: { draft: 0, published: 1, archived: 2 }\n  enum category: { news: 0, blog: 1, press: 2 }\n  enum visibility: { public_post: 0, private_post: 1 }\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-5\">enum\u306b\u95a2\u9023\u3059\u308b\u4fbf\u5229\u306a\u30d8\u30eb\u30d1\u30fc\u30e1\u30bd\u30c3\u30c9<\/h3>\n\n\n\n<p>enum\u3092\u5b9a\u7fa9\u3059\u308b\u3068\u3001\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u4fbf\u5229\u306a\u30e1\u30bd\u30c3\u30c9\u304c\u81ea\u52d5\u7684\u306b\u751f\u6210\u3055\u308c\u307e\u3059\uff1a<\/p>\n\n\n<div id=\"id-e95bdddc-e630-4b02-a48c-f843664a46f4\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u30e1\u30bd\u30c3\u30c9\u30bf\u30a4\u30d7<\/th><th>\u751f\u6210\u3055\u308c\u308b\u30e1\u30bd\u30c3\u30c9\u4f8b<\/th><th>\u7528\u9014<\/th><\/tr><\/thead><tbody><tr><td>\u72b6\u614b\u78ba\u8a8d<\/td><td><code>post.draft?<\/code><\/td><td>\u73fe\u5728\u306e\u72b6\u614b\u3092\u30c1\u30a7\u30c3\u30af<\/td><\/tr><tr><td>\u72b6\u614b\u5909\u66f4<\/td><td><code>post.published!<\/code><\/td><td>\u72b6\u614b\u3092\u5909\u66f4\u3057\u4fdd\u5b58<\/td><\/tr><tr><td>\u30b9\u30b3\u30fc\u30d7<\/td><td><code>Post.published<\/code><\/td><td>\u7279\u5b9a\u306e\u72b6\u614b\u306e\u30ec\u30b3\u30fc\u30c9\u3092\u53d6\u5f97<\/td><\/tr><tr><td>\u9077\u79fb\u5c65\u6b74<\/td><td><code>post.status_was<\/code><\/td><td>\u5909\u66f4\u524d\u306e\u72b6\u614b\u3092\u53d6\u5f97<\/td><\/tr><tr><td>\u4e00\u89a7\u53d6\u5f97<\/td><td><code>Post.statuses<\/code><\/td><td>\u5b9a\u7fa9\u3055\u308c\u305f\u72b6\u614b\u306e\u4e00\u89a7\u3092\u53d6\u5f97<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n<p>\u5b9f\u8df5\u7684\u306a\u4f7f\u7528\u4f8b\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># \u72b6\u614b\u306e\u78ba\u8a8d\u3068\u5909\u66f4\npost = Post.create(status: :draft)\npost.draft?      # =&gt; true\npost.published!  # \u516c\u958b\u72b6\u614b\u306b\u5909\u66f4\npost.published?  # =&gt; true\n\n# \u30b9\u30b3\u30fc\u30d7\u3092\u4f7f\u7528\u3057\u305f\u691c\u7d22\nPost.published   # published\u72b6\u614b\u306e\u8a18\u4e8b\u3092\u5168\u3066\u53d6\u5f97\nPost.not_draft   # draft\u4ee5\u5916\u306e\u8a18\u4e8b\u3092\u53d6\u5f97\n\n# \u4e00\u62ec\u66f4\u65b0\nPost.draft.update_all(status: :published)<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-6\">\u65e5\u672c\u8a9e\u5316\u5bfe\u5fdc\u306e\u5b9f\u8df5\u30c6\u30af\u30cb\u30c3\u30af<\/h3>\n\n\n\n<p>Rails \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067enum\u3092\u65e5\u672c\u8a9e\u5316\u3059\u308b\u65b9\u6cd5\u306b\u3064\u3044\u3066\u8aac\u660e\u3057\u307e\u3059\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>config\/locales\/ja.yml \u3067\u306e\u8a2d\u5b9a<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ja:\n  enums:\n    post:\n      status:\n        draft: '\u4e0b\u66f8\u304d'\n        published: '\u516c\u958b\u4e2d'\n        archived: '\u30a2\u30fc\u30ab\u30a4\u30d6\u6e08\u307f'<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u30e2\u30c7\u30eb\u3067\u306e\u65e5\u672c\u8a9e\u8868\u793a\u7528\u30e1\u30bd\u30c3\u30c9\u5b9f\u88c5<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Post &lt; ApplicationRecord\n  enum status: { draft: 0, published: 1, archived: 2 }\n\n  def status_i18n\n    I18n.t(\"enums.post.status.#{status}\")\n  end\nend<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>ActiveModel::Enum\u62e1\u5f35\u306b\u3088\u308b\u81ea\u52d5\u5316<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># config\/initializers\/enum_help.rb\nmodule EnumHelpers\n  extend ActiveSupport::Concern\n\n  class_methods do\n    def human_enum_name(enum_name, enum_value)\n      I18n.t(\"enums.#{model_name.i18n_key}.#{enum_name}.#{enum_value}\")\n    end\n  end\n\n  def human_enum_value(enum_name)\n    self.class.human_enum_name(enum_name, self.send(enum_name))\n  end\nend\n\nActiveRecord::Base.include EnumHelpers<\/pre>\n\n\n\n<p>\u4f7f\u7528\u4f8b\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">post = Post.create(status: :draft)\npost.human_enum_value(:status)  # =&gt; \"\u4e0b\u66f8\u304d\"\n\n# \u30d3\u30e5\u30fc\u3067\u306e\u8868\u793a\n&lt;%= form.select :status, Post.statuses.keys.map { |s| [Post.human_enum_name(:status, s), s] } %&gt;<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5b9f\u88c5\u65b9\u6cd5\u3092\u7406\u89e3\u3057\u3001\u9069\u5207\u306b\u4f7f\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u4fdd\u5b88\u6027\u304c\u9ad8\u304f\u3001\u4f7f\u3044\u3084\u3059\u3044\u30b3\u30fc\u30c9\u3092\u5b9f\u73fe\u3067\u304d\u307e\u3059\u3002\u307e\u305f\u3001\u65e5\u672c\u8a9e\u5316\u5bfe\u5fdc\u306b\u3088\u308a\u3001\u30a8\u30f3\u30c9\u30e6\u30fc\u30b6\u30fc\u306b\u3068\u3063\u3066\u3082\u5206\u304b\u308a\u3084\u3059\u3044\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u69cb\u7bc9\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-7\">\u5b9f\u8df5\u7684\u306aenum\u30d1\u30bf\u30fc\u30f3\u6d3b\u7528<\/h2>\n\n\n\n<p>enum\u306f\u69d8\u3005\u306a\u30e6\u30fc\u30b9\u30b1\u30fc\u30b9\u3067\u6d3b\u7528\u3067\u304d\u307e\u3059\u3002\u3053\u3053\u3067\u306f\u3001\u5b9f\u969b\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3067\u3088\u304f\u4f7f\u7528\u3055\u308c\u308b\u5b9f\u8df5\u7684\u306a\u30d1\u30bf\u30fc\u30f3\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-8\">\u30b9\u30c6\u30fc\u30bf\u30b9\u7ba1\u7406\u3067\u306e\u6d3b\u7528\u4f8b<\/h3>\n\n\n\n<p>\u53d7\u6ce8\u30b7\u30b9\u30c6\u30e0\u3067\u306e\u6ce8\u6587\u30b9\u30c6\u30fc\u30bf\u30b9\u7ba1\u7406\u306f\u3001enum\u306e\u5178\u578b\u7684\u306a\u4f7f\u7528\u4f8b\u3067\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Order &lt; ApplicationRecord\n  # \u30b9\u30c6\u30fc\u30bf\u30b9\u306e\u9077\u79fb\u3092\u8003\u616e\u3057\u305f\u9806\u5e8f\u4ed8\u3051\u3055\u308c\u305f\u5b9a\u7fa9\n  enum status: {\n    pending: 0,      # \u53d7\u6ce8\u5f85\u3061\n    confirmed: 1,    # \u53d7\u6ce8\u78ba\u5b9a\n    in_progress: 2,  # \u51e6\u7406\u4e2d\n    shipped: 3,      # \u767a\u9001\u6e08\u307f\n    delivered: 4,    # \u914d\u9054\u5b8c\u4e86\n    cancelled: 5,    # \u30ad\u30e3\u30f3\u30bb\u30eb\n    returned: 6      # \u8fd4\u54c1\n  }\n\n  # \u30b9\u30c6\u30fc\u30bf\u30b9\u9077\u79fb\u306e\u5236\u5fa1\n  def can_cancel?\n    %w[pending confirmed in_progress].include?(status)\n  end\n\n  # \u9077\u79fb\u6642\u306e\u51e6\u7406\u3092\u542b\u3080\u30e1\u30bd\u30c3\u30c9\n  def cancel!\n    return false unless can_cancel?\n\n    transaction do\n      cancelled!\n      create_cancel_history!\n      notify_customer_of_cancellation\n    end\n    true\n  end\n\n  # \u30b9\u30c6\u30fc\u30bf\u30b9\u306b\u57fa\u3065\u304f\u30b9\u30b3\u30fc\u30d7\u306e\u62e1\u5f35\n  scope :processing, -&gt; { where(status: %i[confirmed in_progress]) }\n  scope :completed, -&gt; { where(status: %i[delivered]) }\n  scope :problematic, -&gt; { where(status: %i[cancelled returned]) }\nend\n\n# \u4f7f\u7528\u4f8b\norder = Order.create(status: :pending)\norder.confirmed!\nOrder.processing.count # \u51e6\u7406\u4e2d\u306e\u6ce8\u6587\u6570\u3092\u53d6\u5f97<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-9\">\u30d5\u30e9\u30b0\u7ba1\u7406\u3067\u306e\u6d3b\u7528\u4f8b<\/h3>\n\n\n\n<p>\u30e6\u30fc\u30b6\u30fc\u8a2d\u5b9a\u3084\u30d5\u30a3\u30fc\u30c1\u30e3\u30fc\u30d5\u30e9\u30b0\u306e\u7ba1\u7406\u306benum\u3092\u6d3b\u7528\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class UserPreference &lt; ApplicationRecord\n  # \u901a\u77e5\u8a2d\u5b9a\u306e\u7ba1\u7406\n  enum notification_level: {\n    all: 0,          # \u5168\u3066\u306e\u901a\u77e5\u3092\u53d7\u3051\u53d6\u308b\n    important: 1,    # \u91cd\u8981\u306a\u901a\u77e5\u306e\u307f\n    minimal: 2,      # \u6700\u5c0f\u9650\u306e\u901a\u77e5\n    none: 3          # \u901a\u77e5\u30aa\u30d5\n  }\n\n  # \u30e1\u30fc\u30eb\u914d\u4fe1\u983b\u5ea6\u306e\u8a2d\u5b9a\n  enum email_frequency: {\n    realtime: 0,     # \u30ea\u30a2\u30eb\u30bf\u30a4\u30e0\n    daily: 1,        # \u65e5\u6b21\n    weekly: 2,       # \u9031\u6b21\n    monthly: 3       # \u6708\u6b21\n  }\n\n  # \u8907\u6570\u306e\u30d5\u30e9\u30b0\u3092\u7d44\u307f\u5408\u308f\u305b\u305f\u4fbf\u5229\u30e1\u30bd\u30c3\u30c9\n  def receives_immediate_notifications?\n    notification_level == 'all' &amp;&amp; email_frequency == 'realtime'\n  end\n\n  # \u30d0\u30c3\u30c1\u51e6\u7406\u7528\u306e\u30b9\u30b3\u30fc\u30d7\n  scope :daily_digest_targets, -&gt; { where(email_frequency: :daily) }\n  scope :weekly_digest_targets, -&gt; { where(email_frequency: :weekly) }\nend\n\n# \u30d5\u30a3\u30fc\u30c1\u30e3\u30fc\u30d5\u30e9\u30b0\u306e\u7ba1\u7406\nclass Feature &lt; ApplicationRecord\n  enum status: {\n    development: 0,  # \u958b\u767a\u4e2d\n    beta: 1,         # \u30d9\u30fc\u30bf\u7248\n    released: 2,     # \u30ea\u30ea\u30fc\u30b9\u6e08\u307f\n    deprecated: 3    # \u5ec3\u6b62\u4e88\u5b9a\n  }\n\n  # \u30a2\u30af\u30bb\u30b9\u5236\u5fa1\u3068\u306e\u9023\u643a\n  def accessible_by?(user)\n    case status\n    when 'development'\n      user.developer?\n    when 'beta'\n      user.beta_tester?\n    when 'released'\n      true\n    when 'deprecated'\n      false\n    end\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-10\">\u6a29\u9650\u7ba1\u7406\u3067\u306e\u6d3b\u7528\u4f8b<\/h3>\n\n\n\n<p>\u30e6\u30fc\u30b6\u30fc\u306e\u6a29\u9650\u7ba1\u7406\u30b7\u30b9\u30c6\u30e0\u306benum\u3092\u5c0e\u5165\u3059\u308b\u4f8b\u3067\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class User &lt; ApplicationRecord\n  # \u57fa\u672c\u7684\u306a\u6a29\u9650\u30ec\u30d9\u30eb\n  enum role: {\n    guest: 0,\n    user: 1,\n    moderator: 2,\n    admin: 3,\n    super_admin: 4\n  }\n\n  # \u90e8\u9580\u6a29\u9650\u306e\u7ba1\u7406\n  enum department_access: {\n    no_access: 0,\n    viewer: 1,\n    editor: 2,\n    manager: 3\n  }, _prefix: :department\n\n  # \u6a29\u9650\u30c1\u30a7\u30c3\u30af\u306e\u30d8\u30eb\u30d1\u30fc\u30e1\u30bd\u30c3\u30c9\n  def can_edit?(resource)\n    return true if super_admin?\n    return true if admin?\n    return true if moderator? &amp;&amp; resource.moderable?\n    return true if department_manager? &amp;&amp; resource.department_id == department_id\n    false\n  end\n\n  # \u6a29\u9650\u306e\u7d99\u627f\u95a2\u4fc2\u3092\u8003\u616e\u3057\u305f\u30e1\u30bd\u30c3\u30c9\n  def higher_role_than?(other_user)\n    User.roles[role] &gt; User.roles[other_user.role]\n  end\n\n  # \u90e8\u9580\u6a29\u9650\u306b\u57fa\u3065\u304f\u30b9\u30b3\u30fc\u30d7\n  scope :with_management_access, -&gt; { where(department_access: %i[editor manager]) }\n  scope :full_access, -&gt; { where(role: %i[admin super_admin]) }\nend\n\n# \u30a2\u30af\u30bb\u30b9\u5236\u5fa1\u3068\u306e\u9023\u643a\u4f8b\nclass ApplicationController &lt; ActionController::Base\n  def authorize_admin!\n    unless current_user&amp;.admin? || current_user&amp;.super_admin?\n      redirect_to root_path, alert: '\u6a29\u9650\u304c\u3042\u308a\u307e\u305b\u3093'\n    end\n  end\n\n  def authorize_department_access!(minimum_access: :viewer)\n    unless current_user&amp;.department_access.to_s &gt;= minimum_access.to_s\n      redirect_to root_path, alert: '\u90e8\u9580\u3078\u306e\u30a2\u30af\u30bb\u30b9\u6a29\u9650\u304c\u3042\u308a\u307e\u305b\u3093'\n    end\n  end\nend<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5b9f\u88c5\u4f8b\u306f\u3001\u5b9f\u969b\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3067\u3059\u3050\u306b\u6d3b\u7528\u3067\u304d\u308b\u5f62\u3067\u63d0\u4f9b\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u72b6\u6cc1\u306b\u5fdc\u3058\u3066\u9069\u5207\u306b\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u3057\u306a\u304c\u3089\u3001enum\u306e\u5229\u70b9\u3092\u6700\u5927\u9650\u306b\u6d3b\u7528\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-11\">\u5217\u6319\u578b\u3092\u4f7f\u7528\u3059\u308b\u969b\u306e\u6ce8\u610f\u70b9\u3068\u5bfe\u7b56<\/h2>\n\n\n\n<p>enum\u3092\u52b9\u679c\u7684\u306b\u6d3b\u7528\u3059\u308b\u306b\u306f\u3001\u3044\u304f\u3064\u304b\u306e\u91cd\u8981\u306a\u6ce8\u610f\u70b9\u304c\u3042\u308a\u307e\u3059\u3002\u3053\u3053\u3067\u306f\u3001\u5b9f\u88c5\u6642\u306b\u8003\u616e\u3059\u3079\u304d\u70b9\u3068\u5177\u4f53\u7684\u306a\u5bfe\u7b56\u3092\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-12\">\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u6574\u5408\u6027\u3092\u78ba\u4fdd\u3059\u308b\u305f\u3081\u306e\u30de\u30a4\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u8a2d\u8a08<\/h3>\n\n\n\n<p>\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30ec\u30d9\u30eb\u3067\u306e\u6574\u5408\u6027\u78ba\u4fdd\u306f\u3001enum\u3092\u4f7f\u7528\u3059\u308b\u4e0a\u3067\u975e\u5e38\u306b\u91cd\u8981\u3067\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u9069\u5207\u306a\u30ab\u30e9\u30e0\u5b9a\u7fa9<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class CreateArticles &lt; ActiveRecord::Migration[7.0]\n  def change\n    create_table :articles do |t|\n      # NOT NULL\u5236\u7d04\u3068\u30c7\u30d5\u30a9\u30eb\u30c8\u5024\u306e\u8a2d\u5b9a\n      t.integer :status, null: false, default: 0\n      # \u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306e\u8ffd\u52a0\uff08\u983b\u7e41\u306b\u691c\u7d22\u3059\u308b\u5834\u5408\uff09\n      t.index :status\n\n      t.timestamps\n    end\n  end\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>check\u5236\u7d04\u306e\u8ffd\u52a0\uff08PostgreSQL\u4f7f\u7528\u6642\uff09<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class AddStatusConstraintToArticles &lt; ActiveRecord::Migration[7.0]\n  def up\n    # \u6709\u52b9\u306a\u5024\u306e\u307f\u3092\u8a31\u53ef\u3059\u308b\u5236\u7d04\n    execute &lt;&lt;-SQL\n      ALTER TABLE articles\n      ADD CONSTRAINT check_valid_status\n      CHECK (status IN (0, 1, 2));\n    SQL\n  end\n\n  def down\n    execute &lt;&lt;-SQL\n      ALTER TABLE articles\n      DROP CONSTRAINT check_valid_status;\n    SQL\n  end\nend<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u65e2\u5b58\u30c7\u30fc\u30bf\u306e\u79fb\u884c\u6642\u306e\u6ce8\u610f\u70b9<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class MigrateExistingStatusData &lt; ActiveRecord::Migration[7.0]\n  def up\n    # \u5b89\u5168\u306a\u79fb\u884c\u306e\u305f\u3081\u306e\u4e00\u6642\u7684\u306a\u30de\u30c3\u30d4\u30f3\u30b0\n    old_to_new = {\n      'draft' =&gt; 0,\n      'published' =&gt; 1,\n      'archived' =&gt; 2\n    }\n\n    # \u30d0\u30c3\u30c1\u51e6\u7406\u306b\u3088\u308b\u5b89\u5168\u306a\u79fb\u884c\n    Article.find_each do |article|\n      new_status = old_to_new[article.read_attribute(:status)]\n      article.update_column(:status, new_status) if new_status\n    end\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-13\">enum\u306e\u5024\u3092\u5909\u66f4\u3059\u308b\u969b\u306e\u30ea\u30b9\u30af\u3068\u5bfe\u5fdc\u7b56<\/h3>\n\n\n\n<p>enum\u306e\u5024\u3092\u5909\u66f4\u3059\u308b\u969b\u306f\u3001\u4ee5\u4e0b\u306e\u30ea\u30b9\u30af\u3068\u5bfe\u7b56\u3092\u8003\u616e\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u5b89\u5168\u306a\u5024\u306e\u8ffd\u52a0\u65b9\u6cd5<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Article &lt; ApplicationRecord\n  # \u8ffd\u52a0\u306f\u672b\u5c3e\u306b\u884c\u3046\uff08\u65e2\u5b58\u306e\u5024\u306f\u5909\u66f4\u3057\u306a\u3044\uff09\n  enum status: {\n    draft: 0,\n    published: 1,\n    archived: 2,\n    featured: 3  # \u65b0\u3057\u3044\u5024\u306f\u672b\u5c3e\u306b\u8ffd\u52a0\n  }\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u5024\u306e\u5909\u66f4\u304c\u5fc5\u8981\u306a\u5834\u5408\u306e\u5bfe\u5fdc<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Article &lt; ApplicationRecord\n  # \u975e\u63a8\u5968: \u5024\u306e\u5909\u66f4\u306f\u907f\u3051\u308b\n  # enum status: { draft: 0, archived: 1, published: 2 }  # NG\n\n  # \u4ee3\u66ff\u6848: \u65b0\u3057\u3044enum\u3092\u4f5c\u6210\u3057\u3001\u53e4\u3044\u3082\u306e\u306f\u975e\u63a8\u5968\u5316\n  enum legacy_status: { draft: 0, published: 1, archived: 2 }, _prefix: :legacy\n  enum status: { draft: 0, published: 1, archived: 2, featured: 3 }\n\n  # \u79fb\u884c\u7528\u306e\u30d8\u30eb\u30d1\u30fc\u30e1\u30bd\u30c3\u30c9\n  def migrate_legacy_status\n    return unless legacy_status\n\n    case legacy_status\n    when 'draft' then self.status = :draft\n    when 'published' then self.status = :published\n    when 'archived' then self.status = :archived\n    end\n    save\n  end\nend<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u30c7\u30fc\u30bf\u6574\u5408\u6027\u3092\u4fdd\u3064\u305f\u3081\u306e\u4ed5\u7d44\u307f<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Article &lt; ApplicationRecord\n  enum status: { draft: 0, published: 1, archived: 2 }\n\n  # enum\u306e\u5024\u5909\u66f4\u524d\u306e\u691c\u8a3c\n  before_save :validate_status_change\n\n  private\n\n  def validate_status_change\n    return unless status_changed?\n\n    case status\n    when 'published'\n      errors.add(:status, '\u4e0b\u66f8\u304d\u304b\u3089\u306e\u307f\u516c\u958b\u53ef\u80fd\u3067\u3059') unless status_was == 'draft'\n    when 'archived'\n      errors.add(:status, '\u516c\u958b\u6e08\u307f\u8a18\u4e8b\u306e\u307f\u30a2\u30fc\u30ab\u30a4\u30d6\u53ef\u80fd\u3067\u3059') unless status_was == 'published'\n    end\n\n    throw(:abort) if errors.present?\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-14\">\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9\u3067\u306e\u53d6\u308a\u6271\u3044\u65b9<\/h3>\n\n\n\n<p>enum\u3092\u4f7f\u7528\u3059\u308b\u30e2\u30c7\u30eb\u306e\u30c6\u30b9\u30c8\u3067\u306f\u3001\u4ee5\u4e0b\u306e\u30dd\u30a4\u30f3\u30c8\u306b\u6ce8\u610f\u3057\u3066\u30c6\u30b9\u30c8\u3092\u66f8\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u57fa\u672c\u7684\u306a\u30c6\u30b9\u30c8\u30d1\u30bf\u30fc\u30f3<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">RSpec.describe Article, type: :model do\n  describe 'enums' do\n    it 'defines the correct status values' do\n      expect(Article.statuses).to eq({\n        'draft' =&gt; 0,\n        'published' =&gt; 1,\n        'archived' =&gt; 2\n      })\n    end\n\n    it 'provides predicate methods' do\n      article = Article.new(status: :draft)\n      expect(article).to be_draft\n      expect(article).not_to be_published\n    end\n\n    it 'provides scope methods' do\n      draft_article = Article.create(status: :draft)\n      published_article = Article.create(status: :published)\n\n      expect(Article.draft).to include(draft_article)\n      expect(Article.draft).not_to include(published_article)\n    end\n  end\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u72b6\u614b\u9077\u79fb\u306e\u30c6\u30b9\u30c8<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">RSpec.describe Article, type: :model do\n  describe 'status transitions' do\n    let(:article) { Article.create(status: :draft) }\n\n    context 'when publishing' do\n      it 'changes status from draft to published' do\n        expect { article.published! }\n          .to change { article.status }.from('draft').to('published')\n      end\n\n      it 'validates the transition' do\n        archived_article = Article.create(status: :archived)\n        expect { archived_article.published! }\n          .to raise_error(ActiveRecord::RecordInvalid)\n      end\n    end\n  end\nend<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u30ab\u30b9\u30bf\u30e0\u30e1\u30bd\u30c3\u30c9\u306e\u30c6\u30b9\u30c8<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">RSpec.describe Article, type: :model do\n  describe '#publishable?' do\n    let(:article) { Article.new }\n\n    it 'returns true for draft articles' do\n      article.status = :draft\n      expect(article).to be_publishable\n    end\n\n    it 'returns false for published articles' do\n      article.status = :published\n      expect(article).not_to be_publishable\n    end\n  end\n\n  describe '#status_i18n' do\n    it 'returns localized status string' do\n      article = Article.new(status: :draft)\n      expect(article.status_i18n).to eq('\u4e0b\u66f8\u304d')\n    end\n  end\nend<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u6ce8\u610f\u70b9\u3068\u5bfe\u7b56\u3092\u5b9f\u88c5\u3059\u308b\u3053\u3068\u3067\u3001enum\u3092\u4f7f\u7528\u3057\u305f\u30b3\u30fc\u30c9\u306e\u4fe1\u983c\u6027\u3068\u4fdd\u5b88\u6027\u3092\u9ad8\u3081\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u7279\u306b\u3001\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u6574\u5408\u6027\u78ba\u4fdd\u3068\u30c6\u30b9\u30c8\u306e\u5145\u5b9f\u306f\u3001\u9577\u671f\u7684\u306a\u904b\u7528\u306b\u304a\u3044\u3066\u91cd\u8981\u306a\u8981\u7d20\u3068\u306a\u308a\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-15\">enum\u306e\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3068\u30e1\u30f3\u30c6\u30ca\u30f3\u30b9<\/h2>\n\n\n\n<p>\u5927\u898f\u6a21\u306aRails\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067enum\u3092\u904b\u7528\u3059\u308b\u969b\u306e\u91cd\u8981\u306a\u8003\u616e\u70b9\u3068\u3001\u52b9\u679c\u7684\u306a\u30e1\u30f3\u30c6\u30ca\u30f3\u30b9\u624b\u6cd5\u306b\u3064\u3044\u3066\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-16\">\u5927\u898f\u6a21\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306e\u5229\u7528\u6642\u306e\u6ce8\u610f\u70b9<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30e1\u30e2\u30ea\u4f7f\u7528\u91cf\u306e\u6700\u9069\u5316<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Order &lt; ApplicationRecord\n  # \u30e1\u30e2\u30ea\u52b9\u7387\u306e\u826f\u3044\u5b9f\u88c5\n  enum status: {\n    pending: 0,\n    processing: 1,\n    completed: 2\n  }\n\n  # \u30ad\u30e3\u30c3\u30b7\u30e5\u306e\u6d3b\u7528\n  after_commit :cache_status_counts, on: [:create, :update]\n\n  def self.status_counts\n    Rails.cache.fetch('order_status_counts', expires_in: 1.hour) do\n      statuses.keys.index_with do |status|\n        where(status: status).count\n      end\n    end\n  end\n\n  private\n\n  def cache_status_counts\n    self.class.status_counts # \u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u66f4\u65b0\n  end\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>N+1\u30af\u30a8\u30ea\u306e\u9632\u6b62<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class OrdersController &lt; ApplicationController\n  def index\n    # \u60aa\u3044\u4f8b\uff1aN+1\u30af\u30a8\u30ea\u304c\u767a\u751f\n    @orders = Order.all\n    @orders.each do |order|\n      puts order.status # \u5404order\u306b\u5bfe\u3057\u3066\u30af\u30a8\u30ea\u304c\u767a\u751f\n    end\n\n    # \u826f\u3044\u4f8b\uff1a\u5fc5\u8981\u306a\u30c7\u30fc\u30bf\u3092\u4e00\u62ec\u53d6\u5f97\n    @orders = Order.all.includes(:related_models)\n\n    # \u3055\u3089\u306b\u826f\u3044\u4f8b\uff1a\u5fc5\u8981\u306a\u60c5\u5831\u306e\u307f\u3092\u53d6\u5f97\n    @status_counts = Order.group(:status).count\n  end\nend<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u5927\u91cf\u30c7\u30fc\u30bf\u306e\u51e6\u7406<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Order &lt; ApplicationRecord\n  # \u30d0\u30c3\u30c1\u51e6\u7406\u3067\u306e\u52b9\u7387\u7684\u306a\u66f4\u65b0\n  def self.batch_update_expired_orders\n    pending.where('created_at &lt; ?', 24.hours.ago)\n          .in_batches(of: 1000) do |batch|\n      batch.update_all(status: :expired)\n    end\n  end\n\n  # \u975e\u540c\u671f\u51e6\u7406\u306e\u6d3b\u7528\n  def async_status_update(new_status)\n    UpdateOrderStatusJob.perform_later(id, new_status)\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-17\">enum\u3092\u542b\u3080\u30e2\u30c7\u30eb\u306e\u30ea\u30d5\u30a1\u30af\u30bf\u30ea\u30f3\u30b0\u624b\u6cd5<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u72b6\u614b\u9077\u79fb\u306e\u30ea\u30d5\u30a1\u30af\u30bf\u30ea\u30f3\u30b0<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># \u30ea\u30d5\u30a1\u30af\u30bf\u30ea\u30f3\u30b0\u524d\nclass Order &lt; ApplicationRecord\n  enum status: { pending: 0, confirmed: 1, shipped: 2 }\n\n  def confirm!\n    update!(status: :confirmed)\n  end\nend\n\n# \u30ea\u30d5\u30a1\u30af\u30bf\u30ea\u30f3\u30b0\u5f8c\uff1a\u72b6\u614b\u9077\u79fb\u3092\u5c02\u7528\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u306b\u5206\u96e2\nmodule OrderStateMachine\n  extend ActiveSupport::Concern\n\n  included do\n    enum status: { pending: 0, confirmed: 1, shipped: 2 }\n\n    include AASM\n\n    aasm column: :status, enum: true do\n      state :pending, initial: true\n      state :confirmed\n      state :shipped\n\n      event :confirm do\n        transitions from: :pending, to: :confirmed\n      end\n\n      event :ship do\n        transitions from: :confirmed, to: :shipped\n      end\n    end\n  end\nend\n\nclass Order &lt; ApplicationRecord\n  include OrderStateMachine\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u30d3\u30b8\u30cd\u30b9\u30ed\u30b8\u30c3\u30af\u306e\u5206\u96e2<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># \u8cac\u52d9\u306e\u5206\u96e2\nclass OrderStatus\n  include ActiveModel::Model\n\n  def initialize(order)\n    @order = order\n  end\n\n  def can_transition_to?(new_status)\n    case @order.status\n    when 'pending'\n      ['confirmed'].include?(new_status.to_s)\n    when 'confirmed'\n      ['shipped'].include?(new_status.to_s)\n    else\n      false\n    end\n  end\nend\n\nclass Order &lt; ApplicationRecord\n  enum status: { pending: 0, confirmed: 1, shipped: 2 }\n\n  def status_manager\n    @status_manager ||= OrderStatus.new(self)\n  end\n\n  def update_status!(new_status)\n    if status_manager.can_transition_to?(new_status)\n      update!(status: new_status)\n    else\n      errors.add(:status, :invalid_transition)\n      raise ActiveRecord::RecordInvalid, self\n    end\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-18\">\u904b\u7528\u6642\u306e\u30c8\u30e9\u30d6\u30eb\u30b7\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u3088\u304f\u3042\u308b\u554f\u984c\u3068\u89e3\u6c7a\u7b56<\/strong><\/li>\n<\/ol>\n\n\n<div id=\"id-5d486dac-e65c-4b87-af77-c6657762cc83\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u554f\u984c<\/th><th>\u539f\u56e0<\/th><th>\u89e3\u6c7a\u7b56<\/th><\/tr><\/thead><tbody><tr><td>\u4e88\u671f\u305b\u306c\u72b6\u614b\u9077\u79fb<\/td><td>\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u4e0d\u8db3<\/td><td>\u72b6\u614b\u9077\u79fb\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u3092\u8ffd\u52a0<\/td><\/tr><tr><td>N+1\u30af\u30a8\u30ea<\/td><td>\u95a2\u9023\u30c7\u30fc\u30bf\u306e\u500b\u5225\u53d6\u5f97<\/td><td>includes\/preload\u306e\u9069\u5207\u306a\u4f7f\u7528<\/td><\/tr><tr><td>\u30e1\u30e2\u30ea\u4f7f\u7528\u91cf\u306e\u5897\u5927<\/td><td>\u5927\u91cf\u306eenum\u5b9a\u7fa9<\/td><td>\u5fc5\u8981\u6700\u5c0f\u9650\u306e\u5024\u5b9a\u7fa9\u3068\u30ad\u30e3\u30c3\u30b7\u30e5\u306e\u6d3b\u7528<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u30c7\u30d0\u30c3\u30b0\u3068\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># \u30ed\u30b0\u51fa\u529b\u306e\u5f37\u5316\nclass Order &lt; ApplicationRecord\n  enum status: { pending: 0, confirmed: 1, shipped: 2 }\n\n  after_update :log_status_change, if: :saved_change_to_status?\n\n  private\n\n  def log_status_change\n    Rails.logger.info(\n      \"Order##{id} status changed from \" \\\n      \"#{status_before_last_save} to #{status} \" \\\n      \"(#{Time.current})\"\n    )\n  end\nend\n\n# \u30e2\u30cb\u30bf\u30ea\u30f3\u30b0\u306e\u5b9f\u88c5\nclass OrderStatusMetrics\n  def self.collect_metrics\n    stats = Order.group(:status).count\n\n    stats.each do |status, count|\n      StatsD.gauge(\"orders.status.#{status}\", count)\n    end\n  end\nend<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u6539\u5584\u306e\u305f\u3081\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u8a2d\u8a08<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class AddOptimizedIndexesToOrders &lt; ActiveRecord::Migration[7.0]\n  def change\n    # \u8907\u5408\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306e\u8ffd\u52a0\n    add_index :orders, [:status, :created_at]\n\n    # \u90e8\u5206\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306e\u8ffd\u52a0\uff08\u7279\u5b9a\u306e\u72b6\u614b\u306e\u307f\uff09\n    add_index :orders, :status, \n              where: \"status IN (0, 1)\", \n              name: 'index_orders_on_active_statuses'\n  end\nend<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5b9f\u8df5\u7684\u306a\u30a2\u30d7\u30ed\u30fc\u30c1\u3092\u9069\u7528\u3059\u308b\u3053\u3068\u3067\u3001enum\u3092\u4f7f\u7528\u3057\u305f\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u4fdd\u5b88\u6027\u3068\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3092\u7d99\u7d9a\u7684\u306b\u6539\u5584\u3067\u304d\u307e\u3059\u3002\u7279\u306b\u5927\u898f\u6a21\u306a\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306f\u3001\u3053\u308c\u3089\u306e\u8003\u616e\u70b9\u304c\u91cd\u8981\u306b\u306a\u3063\u3066\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-19\">\u767a\u5c55\u7684\u306aenum\u6d3b\u7528\u30c6\u30af\u30cb\u30c3\u30af<\/h2>\n\n\n\n<p>enum\u306e\u57fa\u672c\u7684\u306a\u6a5f\u80fd\u3092\u7406\u89e3\u3057\u305f\u3089\u3001\u3088\u308a\u9ad8\u5ea6\u306a\u6d3b\u7528\u65b9\u6cd5\u3092\u7fd2\u5f97\u3059\u308b\u3053\u3068\u3067\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u54c1\u8cea\u3092\u3055\u3089\u306b\u5411\u4e0a\u3055\u305b\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-20\">\u30ab\u30b9\u30bf\u30e0\u30b9\u30b3\u30fc\u30d7\u3068\u306e\u7d44\u307f\u5408\u308f\u305b<\/h3>\n\n\n\n<p>enum\u306e\u6a5f\u80fd\u3092\u62e1\u5f35\u3057\u3001\u3088\u308a\u67d4\u8edf\u306a\u691c\u7d22\u3084\u7d5e\u308a\u8fbc\u307f\u3092\u5b9f\u73fe\u3059\u308b\u65b9\u6cd5\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Post &lt; ApplicationRecord\n  enum status: { draft: 0, review: 1, published: 2, archived: 3 }\n  enum visibility: { public_post: 0, private_post: 1, members_only: 2 }\n\n  # \u8907\u6570\u306eenum\u3092\u7d44\u307f\u5408\u308f\u305b\u305f\u30b9\u30b3\u30fc\u30d7\n  scope :visible_to, -&gt;(user) {\n    if user&amp;.admin?\n      all\n    elsif user&amp;.member?\n      where(visibility: [:public_post, :members_only])\n    else\n      where(visibility: :public_post)\n    end\n  }\n\n  # \u65e5\u4ed8\u6761\u4ef6\u3068enum\u3092\u7d44\u307f\u5408\u308f\u305b\u305f\u30b9\u30b3\u30fc\u30d7\n  scope :recently_published, -&gt; {\n    published.where('published_at &gt; ?', 30.days.ago)\n  }\n\n  # \u8907\u6570\u306e\u6761\u4ef6\u3092\u7d44\u307f\u5408\u308f\u305b\u305f\u9ad8\u5ea6\u306a\u30b9\u30b3\u30fc\u30d7\n  scope :featured_content, -&gt; {\n    published\n      .where(visibility: :public_post)\n      .where('featured = true')\n      .order(published_at: :desc)\n  }\n\n  # enum\u306e\u5024\u306b\u57fa\u3065\u304f\u52d5\u7684\u306a\u30b9\u30b3\u30fc\u30d7\n  def self.with_status_higher_than(status)\n    where('status &gt; ?', statuses[status])\n  end\n\n  # \u72b6\u614b\u9077\u79fb\u3092\u8003\u616e\u3057\u305f\u30b9\u30b3\u30fc\u30d7\n  scope :publishable, -&gt; {\n    draft.or(review.where('reviewed_at &lt;= ?', 24.hours.ago))\n  }\nend\n\n# \u4f7f\u7528\u4f8b\nPost.visible_to(current_user)\n    .with_status_higher_than(:draft)\n    .recently_published<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-21\">API\u30ec\u30b9\u30dd\u30f3\u30b9\u3067\u306e\u52b9\u679c\u7684\u306a\u6d3b\u7528\u65b9\u6cd5<\/h3>\n\n\n\n<p>RESTful API\u3067enum\u3092\u52b9\u679c\u7684\u306b\u4f7f\u7528\u3059\u308b\u65b9\u6cd5\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># \u30e2\u30c7\u30eb\u3067\u306e\u6e96\u5099\nclass Task &lt; ApplicationRecord\n  enum priority: { low: 0, medium: 1, high: 2, urgent: 3 }\n  enum status: { todo: 0, in_progress: 1, done: 2, cancelled: 3 }\n\n  # API\u7528\u306e\u30e1\u30bd\u30c3\u30c9\u8ffd\u52a0\n  def as_json(options = {})\n    super(options.merge(\n      methods: [:priority_label, :status_label],\n      except: [:priority, :status]\n    ))\n  end\n\n  def priority_label\n    I18n.t(\"enums.task.priority.#{priority}\")\n  end\n\n  def status_label\n    I18n.t(\"enums.task.status.#{status}\")\n  end\nend\n\n# \u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u3067\u306e\u5b9f\u88c5\nclass Api::V1::TasksController &lt; Api::V1::BaseController\n  def index\n    tasks = Task.all\n    render json: {\n      tasks: tasks,\n      available_priorities: Task.priorities.keys,\n      available_statuses: Task.statuses.keys\n    }\n  end\n\n  def update\n    task = Task.find(params[:id])\n    if task.update(task_params)\n      render json: {\n        task: task,\n        transitions: {\n          available_next_statuses: task.available_next_statuses\n        }\n      }\n    else\n      render json: { errors: task.errors }, status: :unprocessable_entity\n    end\n  end\n\n  private\n\n  def task_params\n    params.require(:task).permit(:priority, :status)\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-22\">\u4ed6\u306egem\u3068\u306e\u9023\u643a\u6d3b\u7528\u4f8b<\/h3>\n\n\n\n<p>\u4eba\u6c17\u306egem\u3068enum\u3092\u7d44\u307f\u5408\u308f\u305b\u305f\u9ad8\u5ea6\u306a\u5b9f\u88c5\u4f8b\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>AASM\uff08\u72b6\u614b\u9077\u79fb\u7ba1\u7406\uff09\u3068\u306e\u9023\u643a<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Order &lt; ApplicationRecord\n  enum status: { \n    pending: 0, \n    confirmed: 1, \n    processing: 2, \n    shipped: 3, \n    delivered: 4, \n    cancelled: 5 \n  }\n\n  include AASM\n\n  aasm column: :status, enum: true do\n    state :pending, initial: true\n    state :confirmed, :processing, :shipped, :delivered, :cancelled\n\n    event :confirm do\n      transitions from: :pending, to: :confirmed\n      after do\n        notify_customer\n        update_inventory\n      end\n    end\n\n    event :process do\n      transitions from: :confirmed, to: :processing\n      after do\n        create_shipping_label\n      end\n    end\n\n    event :ship do\n      transitions from: :processing, to: :shipped\n      after do\n        send_tracking_number\n      end\n    end\n  end\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Ransack\uff08\u691c\u7d22\u6a5f\u80fd\uff09\u3068\u306e\u9023\u643a<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Project &lt; ApplicationRecord\n  enum status: { planning: 0, active: 1, on_hold: 2, completed: 3 }\n  enum priority: { low: 0, medium: 1, high: 2 }\n\n  # Ransack\u306e\u30b5\u30fc\u30c1\u30b9\u30b3\u30fc\u30d7\u5b9a\u7fa9\n  ransacker :status_text do\n    Arel.sql(\"(CASE status \n              WHEN 0 THEN 'planning'\n              WHEN 1 THEN 'active'\n              WHEN 2 THEN 'on_hold'\n              WHEN 3 THEN 'completed'\n              END)\")\n  end\n\n  # \u512a\u5148\u5ea6\u306b\u3088\u308b\u691c\u7d22\n  ransacker :priority_value do\n    Arel.sql('priority')\n  end\nend\n\n# \u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u3067\u306e\u4f7f\u7528\nclass ProjectsController &lt; ApplicationController\n  def index\n    @q = Project.ransack(params[:q])\n    @projects = @q.result.includes(:team)\n  end\nend\n\n# \u30d3\u30e5\u30fc\u3067\u306e\u4f7f\u7528\n= search_form_for @q do |f|\n  = f.select :status_text_eq,\n             Project.statuses.map { |k, v| [k.humanize, k] },\n             include_blank: true\n  = f.select :priority_value_eq,\n             Project.priorities.map { |k, v| [k.humanize, v] },\n             include_blank: true<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>ActiveAdmin\uff08\u7ba1\u7406\u753b\u9762\uff09\u3068\u306e\u9023\u643a<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ActiveAdmin.register Post do\n  permit_params :title, :content, :status, :visibility\n\n  scope :all\n  Post.statuses.each do |status, _|\n    scope status.to_sym\n  end\n\n  filter :status,\n         as: :select,\n         collection: Post.statuses.keys.map { |s| [s.humanize, s] }\n\n  form do |f|\n    f.inputs do\n      f.input :title\n      f.input :content\n      f.input :status,\n              as: :select,\n              collection: Post.statuses.keys.map { |s| [s.humanize, s] }\n      f.input :visibility,\n              as: :select,\n              collection: Post.visibilities.keys.map { |v| [v.humanize, v] }\n    end\n    f.actions\n  end\n\n  index do\n    selectable_column\n    id_column\n    column :title\n    column :status do |post|\n      status_tag post.status\n    end\n    column :visibility\n    actions\n  end\nend<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u9ad8\u5ea6\u306a\u30c6\u30af\u30cb\u30c3\u30af\u3092\u6d3b\u7528\u3059\u308b\u3053\u3068\u3067\u3001enum\u306e\u5229\u70b9\u3092\u6700\u5927\u9650\u306b\u6d3b\u304b\u3057\u305f\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u958b\u767a\u304c\u53ef\u80fd\u306b\u306a\u308a\u307e\u3059\u3002\u7279\u306b\u3001\u4ed6\u306egem\u3068\u306e\u9023\u643a\u306f\u3001\u958b\u767a\u52b9\u7387\u3068\u4fdd\u5b88\u6027\u306e\u5411\u4e0a\u306b\u5927\u304d\u304f\u8ca2\u732e\u3057\u307e\u3059\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Warning: Undefined array key &#8220;is_admin&#8221; in \/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/ &#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":{"0":"post-1402","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-ruby","7":"nothumb"},"_links":{"self":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/1402","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1402"}],"version-history":[{"count":1,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/1402\/revisions"}],"predecessor-version":[{"id":1403,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/1402\/revisions\/1403"}],"wp:attachment":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1402"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1402"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1402"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}