{"id":1495,"date":"2025-03-24T08:50:35","date_gmt":"2025-03-23T23:50:35","guid":{"rendered":"https:\/\/dexall.co.jp\/articles\/?p=1495"},"modified":"2025-03-24T08:50:35","modified_gmt":"2025-03-23T23:50:35","slug":"ruby%e3%81%aepresent%e3%83%a1%e3%82%bd%e3%83%83%e3%83%89%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bc%e3%82%ac%e3%82%a4%e3%83%89%ef%bc%9a%e4%bd%bf%e3%81%84%e6%96%b9%e3%81%a85%e3%81%a4%e3%81%ae%e5%ae%9f","status":"publish","type":"post","link":"https:\/\/dexall.co.jp\/articles\/?p=1495","title":{"rendered":"Ruby\u306epresent\u30e1\u30bd\u30c3\u30c9\u30de\u30b9\u30bf\u30fc\u30ac\u30a4\u30c9\uff1a\u4f7f\u3044\u65b9\u30685\u3064\u306e\u5b9f\u8df5\u7684\u306a\u30c6\u30af\u30cb\u30c3\u30af"},"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\">present\u30e1\u30bd\u30c3\u30c9\u306e\u57fa\u790e\u77e5\u8b58<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-1\">present\u30e1\u30bd\u30c3\u30c9\u3068\u306f\uff1a\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u5b58\u5728\u78ba\u8a8d\u306e\u65b0\u6a19\u6e96<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-2\">nil?\u3001empty?\u3001blank?\u3068\u306e\u9055\u3044\u3092\u5b8c\u5168\u306b\u7406\u89e3\u3059\u308b<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-3\">present\u30e1\u30bd\u30c3\u30c9\u306e\u5b9f\u8df5\u7684\u306a\u4f7f\u3044\u65b9<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-4\">ActiveRecord\u3067\u306e\u30c7\u30fc\u30bf\u691c\u8a3c\u306b\u304a\u3051\u308b\u6d3b\u7528\u4f8b<\/a>      <\/li>      <li>        <a href=\"#i-5\">\u6761\u4ef6\u5206\u5c90\u3067\u306e\u52b9\u679c\u7684\u306a\u4f7f\u7528\u65b9\u6cd5<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-6\">\u914d\u5217\u3084\u30cf\u30c3\u30b7\u30e5\u3067\u306epresent\u30e1\u30bd\u30c3\u30c9\u306e\u5a01\u529b<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-7\">present\u30e1\u30bd\u30c3\u30c9\u3092\u4f7f\u3063\u305f\u653b\u7565\u30c6\u30af\u30cb\u30c3\u30af<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-8\">\u30e1\u30bd\u30c3\u30c9\u30c1\u30a7\u30fc\u30f3\u3067\u306epresent\u30e1\u30bd\u30c3\u30c9\u306e\u6d3b\u7528<\/a>      <\/li>      <li>        <a href=\"#i-9\">\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u3067\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-10\">\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3092\u8003\u616e\u3057\u305f\u4f7f\u7528\u65b9\u6cd5<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-11\">\u3088\u304f\u3042\u308b\u30df\u30b9\u3068\u89e3\u6c7a\u7b56<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-12\">\u5b58\u5728 vs \u5b58\u5728\uff1a\u9069\u5207\u306a\u4f7f\u3044\u65b9<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-13\">nil\u5bfe\u7b56\u3068\u30a8\u30e9\u30fc\u56de\u907f\u306e\u30c6\u30af\u30cb\u30c3\u30af<\/a>      <\/li>    <\/ul>  <\/li>  <li class=\"last\">    <a href=\"#i-14\">\u5b9f\u52d9\u3067\u306e\u5fdc\u7528\u3068\u767a\u5c55\u7684\u306a\u4f7f\u3044\u65b9<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-15\">\u5927\u898f\u6a21\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306e\u6d3b\u7528\u4e8b\u4f8b<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-16\">\u30ab\u30b9\u30bf\u30e0\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u3067\u306e\u7d44\u307f\u8fbc\u307f\u65b9<\/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\">present\u30e1\u30bd\u30c3\u30c9\u306e\u57fa\u790e\u77e5\u8b58<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-1\">present\u30e1\u30bd\u30c3\u30c9\u3068\u306f\uff1a\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u5b58\u5728\u78ba\u8a8d\u306e\u65b0\u6a19\u6e96<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ruby\u306epresent\u30e1\u30bd\u30c3\u30c9\u306f\u3001ActiveSupport\uff08Ruby on Rails\u306e\u57fa\u76e4\u30e9\u30a4\u30d6\u30e9\u30ea\uff09\u304c\u63d0\u4f9b\u3059\u308b\u4fbf\u5229\u306a\u30e1\u30bd\u30c3\u30c9\u3067\u3001\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u304c\u300c\u610f\u5473\u306e\u3042\u308b\u5024\u3068\u3057\u3066\u5b58\u5728\u3059\u308b\u304b\u300d\u3092\u5224\u5b9a\u3057\u307e\u3059\u3002\u3053\u306e\u30e1\u30bd\u30c3\u30c9\u306f\u7279\u306b Rails \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306e\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u5b58\u5728\u30c1\u30a7\u30c3\u30af\u3092\u76f4\u611f\u7684\u306b\u884c\u3048\u308b\u3088\u3046\u306b\u3059\u308b\u5f37\u529b\u306a\u30c4\u30fc\u30eb\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=\"\"># present\u30e1\u30bd\u30c3\u30c9\u306e\u57fa\u672c\u7684\u306a\u4f7f\u3044\u65b9\nuser_name = \"John\"\nuser_name.present?  # =&gt; true\n\nempty_string = \"\"\nempty_string.present?  # =&gt; false\n\nnil_value = nil\nnil_value.present?  # =&gt; false\n\nempty_array = []\nempty_array.present?  # =&gt; false\n\nfilled_array = [1, 2, 3]\nfilled_array.present?  # =&gt; true<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">present\u30e1\u30bd\u30c3\u30c9\u306f\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u5024\u3092\u300c\u5b58\u5728\u3057\u306a\u3044\u300d\u3068\u5224\u5b9a\u3057\u307e\u3059\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>nil<\/li>\n\n\n\n<li>\u7a7a\u6587\u5b57\u5217 (\u201c\u201d)<\/li>\n\n\n\n<li>\u7a7a\u767d\u6587\u5b57\u306e\u307f\u306e\u6587\u5b57\u5217 (\u201d \u201c, \u201c\\n\u201d, \u201c\\t\u201d \u306a\u3069)<\/li>\n\n\n\n<li>\u7a7a\u306e\u914d\u5217 ([])<\/li>\n\n\n\n<li>\u7a7a\u306e\u30cf\u30c3\u30b7\u30e5 ({})<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-2\">nil?\u3001empty?\u3001blank?\u3068\u306e\u9055\u3044\u3092\u5b8c\u5168\u306b\u7406\u89e3\u3059\u308b<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ruby\u306b\u306f\u5b58\u5728\u78ba\u8a8d\u306e\u305f\u3081\u306e\u8907\u6570\u306e\u30e1\u30bd\u30c3\u30c9\u304c\u7528\u610f\u3055\u308c\u3066\u3044\u307e\u3059\u304c\u3001\u305d\u308c\u305e\u308c\u7570\u306a\u308b\u7528\u9014\u3068\u5224\u5b9a\u57fa\u6e96\u3092\u6301\u3063\u3066\u3044\u307e\u3059\u3002\u4ee5\u4e0b\u306e\u6bd4\u8f03\u8868\u3067\u9055\u3044\u3092\u660e\u78ba\u306b\u3057\u307e\u3057\u3087\u3046\uff1a<\/p>\n\n\n<div id=\"id-3e202908-423e-4e1b-9d3a-27c8232e3d88\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u30e1\u30bd\u30c3\u30c9<\/th><th>\u5224\u5b9a\u57fa\u6e96<\/th><th>nil<\/th><th>\u7a7a\u6587\u5b57<\/th><th>\u7a7a\u767d\u6587\u5b57<\/th><th>\u7a7a\u914d\u5217<\/th><th>false<\/th><th>\u6570\u50240<\/th><\/tr><\/thead><tbody><tr><td>nil?<\/td><td>\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u304cnil\u304b<\/td><td>true<\/td><td>false<\/td><td>false<\/td><td>false<\/td><td>false<\/td><td>false<\/td><\/tr><tr><td>empty?<\/td><td>\u8981\u7d20\u6570\u304c0\u304b<\/td><td>\u30a8\u30e9\u30fc<\/td><td>true<\/td><td>false<\/td><td>true<\/td><td>\u30a8\u30e9\u30fc<\/td><td>\u30a8\u30e9\u30fc<\/td><\/tr><tr><td>blank?<\/td><td>\u610f\u5473\u306e\u3042\u308b\u5024\u3068\u3057\u3066\u5b58\u5728\u3057\u306a\u3044\u304b<\/td><td>true<\/td><td>true<\/td><td>true<\/td><td>true<\/td><td>true<\/td><td>false<\/td><\/tr><tr><td>present?<\/td><td>\u610f\u5473\u306e\u3042\u308b\u5024\u3068\u3057\u3066\u5b58\u5728\u3059\u308b\u304b<\/td><td>false<\/td><td>false<\/td><td>false<\/td><td>false<\/td><td>false<\/td><td>true<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\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=\"\"># \u5404\u30e1\u30bd\u30c3\u30c9\u306e\u9055\u3044\u3092\u793a\u3059\u5b9f\u8df5\u7684\u306a\u4f8b\nuser_name = nil\nuser_name.nil?     # =&gt; true\nuser_name.blank?   # =&gt; true\nuser_name.present? # =&gt; false\n# user_name.empty? # =&gt; NoMethodError: undefined method `empty?' for nil:NilClass\n\nuser_name = \"\"\nuser_name.nil?     # =&gt; false\nuser_name.empty?   # =&gt; true\nuser_name.blank?   # =&gt; true\nuser_name.present? # =&gt; false\n\nuser_name = \" \\n\\t\"\nuser_name.nil?     # =&gt; false\nuser_name.empty?   # =&gt; false\nuser_name.blank?   # =&gt; true\nuser_name.present? # =&gt; false\n\nuser_name = \"John\"\nuser_name.nil?     # =&gt; false\nuser_name.empty?   # =&gt; false\nuser_name.blank?   # =&gt; false\nuser_name.present? # =&gt; true<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">present\u30e1\u30bd\u30c3\u30c9\u3092\u4f7f\u7528\u3059\u308b\u4e3b\u306a\u30e1\u30ea\u30c3\u30c8\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u76f4\u611f\u7684\u306a\u30b3\u30fc\u30c9\u8a18\u8ff0\u304c\u53ef\u80fd<\/li>\n\n\n\n<li>nil\/empty\/\u7a7a\u767d\u6587\u5b57\u3092\u4e00\u62ec\u3067\u30c1\u30a7\u30c3\u30af\u53ef\u80fd<\/li>\n\n\n\n<li>\u30e1\u30bd\u30c3\u30c9\u30c1\u30a7\u30fc\u30f3\u3068\u306e\u76f8\u6027\u304c\u826f\u3044<\/li>\n\n\n\n<li>\u6761\u4ef6\u5206\u5c90\u304c\u30b7\u30f3\u30d7\u30eb\u306b\u66f8\u3051\u308b<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">\u7279\u306b\u6ce8\u610f\u3059\u3079\u304d\u70b9\u3068\u3057\u3066\u3001present\u30e1\u30bd\u30c3\u30c9\u306fblank?\u30e1\u30bd\u30c3\u30c9\u306e\u5426\u5b9a\u5f62\u3068\u3057\u3066\u5b9f\u88c5\u3055\u308c\u3066\u3044\u307e\u3059\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=\"\"># present\u30e1\u30bd\u30c3\u30c9\u306e\u5185\u90e8\u5b9f\u88c5\uff08\u7c21\u7565\u5316\uff09\ndef present?\n  !blank?\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u3053\u306e\u305f\u3081\u3001\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3092\u6975\u9650\u307e\u3067\u91cd\u8996\u3059\u308b\u5834\u5408\u306f\u3001\u5177\u4f53\u7684\u306b\u5fc5\u8981\u306a\u5224\u5b9a\uff08nil?\u3084empty?\uff09\u3092\u76f4\u63a5\u4f7f\u7528\u3059\u308b\u3053\u3068\u3092\u691c\u8a0e\u3057\u3066\u3082\u826f\u3044\u3067\u3057\u3087\u3046\u3002\u305f\u3060\u3057\u3001\u901a\u5e38\u306e\u4f7f\u7528\u3067\u306f\u53ef\u8aad\u6027\u3068\u30e1\u30f3\u30c6\u30ca\u30f3\u30b9\u6027\u306e\u89b3\u70b9\u304b\u3089present\u30e1\u30bd\u30c3\u30c9\u306e\u4f7f\u7528\u304c\u63a8\u5968\u3055\u308c\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-3\">present\u30e1\u30bd\u30c3\u30c9\u306e\u5b9f\u8df5\u7684\u306a\u4f7f\u3044\u65b9<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-4\">ActiveRecord\u3067\u306e\u30c7\u30fc\u30bf\u691c\u8a3c\u306b\u304a\u3051\u308b\u6d3b\u7528\u4f8b<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">ActiveRecord\u3067\u306e\u30c7\u30fc\u30bf\u64cd\u4f5c\u6642\u3001present\u30e1\u30bd\u30c3\u30c9\u306f\u7279\u306b\u5a01\u529b\u3092\u767a\u63ee\u3057\u307e\u3059\u3002\u4ee5\u4e0b\u306b\u4ee3\u8868\u7684\u306a\u4f7f\u7528\u30d1\u30bf\u30fc\u30f3\u3092\u793a\u3057\u307e\u3059\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=\"\">class Order &lt; ApplicationRecord\n  belongs_to :user\n  has_many :order_items\n\n  # \u6ce8\u6587\u78ba\u5b9a\u524d\u306e\u691c\u8a3c\n  def validate_order\n    return false unless user.present? &amp;&amp; order_items.present?\n\n    # \u914d\u9001\u5148\u60c5\u5831\u306e\u691c\u8a3c\n    if shipping_address.present?\n      calculate_shipping_fee\n    else\n      errors.add(:shipping_address, \"\u914d\u9001\u5148\u4f4f\u6240\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\")\n      return false\n    end\n\n    true\n  end\n\n  # \u6ce8\u6587\u5408\u8a08\u984d\u306e\u8a08\u7b97\n  def total_amount\n    return 0 unless order_items.present?\n\n    order_items.sum(&amp;:price)\n  end\nend\n\n# \u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u3067\u306e\u4f7f\u7528\u4f8b\nclass OrdersController &lt; ApplicationController\n  def confirm\n    @order = current_user.orders.build(order_params)\n\n    if @order.present? &amp;&amp; @order.validate_order\n      render :confirm\n    else\n      render :new\n    end\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-5\">\u6761\u4ef6\u5206\u5c90\u3067\u306e\u52b9\u679c\u7684\u306a\u4f7f\u7528\u65b9\u6cd5<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">present\u30e1\u30bd\u30c3\u30c9\u3092\u4f7f\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u6761\u4ef6\u5206\u5c90\u3092\u7c21\u6f54\u304b\u3064\u610f\u56f3\u304c\u660e\u78ba\u306b\u8a18\u8ff0\u3067\u304d\u307e\u3059\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=\"\"># \u5f93\u6765\u306e\u66f8\u304d\u65b9\ndef process_user_data\n  if user &amp;&amp; !user.name.nil? &amp;&amp; !user.name.empty?\n    # \u30e6\u30fc\u30b6\u30fc\u540d\u304c\u5b58\u5728\u3059\u308b\u5834\u5408\u306e\u51e6\u7406\n  end\nend\n\n# present\u30e1\u30bd\u30c3\u30c9\u3092\u4f7f\u7528\u3057\u305f\u5834\u5408\ndef process_user_data\n  if user&amp;.name.present?\n    # \u30e6\u30fc\u30b6\u30fc\u540d\u304c\u5b58\u5728\u3059\u308b\u5834\u5408\u306e\u51e6\u7406\n  end\nend\n\n# \u6761\u4ef6\u5206\u5c90\u3067\u306e\u6d3b\u7528\u4f8b\nclass UserNotificationService\n  def send_notification(user)\n    return unless user.present? &amp;&amp; user.email.present?\n\n    if user.notification_preference.present?\n      send_by_preference(user)\n    else\n      send_default_notification(user)\n    end\n  end\n\n  private\n\n  def send_by_preference(user)\n    case user.notification_preference.channel\n    when 'email'\n      send_email(user) if user.email.present?\n    when 'sms'\n      send_sms(user) if user.phone.present?\n    end\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-6\">\u914d\u5217\u3084\u30cf\u30c3\u30b7\u30e5\u3067\u306epresent\u30e1\u30bd\u30c3\u30c9\u306e\u5a01\u529b<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u30c7\u30fc\u30bf\u69cb\u9020\u3067\u306e\u6d3b\u7528\u4f8b\u3092\u898b\u3066\u3044\u304d\u307e\u3057\u3087\u3046\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=\"\"># \u914d\u5217\u3067\u306e\u4f7f\u7528\u4f8b\nclass TaskManager\n  def process_tasks(tasks)\n    return unless tasks.present?\n\n    tasks.each do |task|\n      next unless task.attributes.present?\n      process_single_task(task)\n    end\n  end\n\n  # \u8907\u6570\u306e\u914d\u5217\u3092\u6271\u3046\u5834\u5408\n  def assign_tasks(users, tasks)\n    return unless users.present? &amp;&amp; tasks.present?\n\n    users.each do |user|\n      available_tasks = tasks.select { |task| \n        task.present? &amp;&amp; task.assignee_id.nil? \n      }\n\n      assign_user_tasks(user, available_tasks)\n    end\n  end\nend\n\n# \u30cf\u30c3\u30b7\u30e5\u3067\u306e\u4f7f\u7528\u4f8b\nclass ConfigurationManager\n  def apply_settings(settings)\n    return unless settings.present?\n\n    # \u30c7\u30d5\u30a9\u30eb\u30c8\u8a2d\u5b9a\u3068\u30de\u30fc\u30b8\n    current_settings.merge!(\n      settings.select { |_key, value| value.present? }\n    )\n  end\n\n  def validate_configuration(config)\n    return false unless config.present?\n\n    required_keys = %w[api_key base_url timeout]\n    required_keys.all? { |key| config[key].present? }\n  end\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u5b9f\u8df5\u7684\u306aTips\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30e1\u30bd\u30c3\u30c9\u30c1\u30a7\u30fc\u30f3\u3067\u306e\u4f7f\u7528\uff1a<\/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=\"\">User.where(active: true)\n    .includes(:posts)\n    .select { |user| user.posts.present? }<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u8907\u6570\u6761\u4ef6\u306e\u7d44\u307f\u5408\u308f\u305b\uff1a<\/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=\"\">def process_order(order)\n  return unless order.present? &amp;&amp; \n                order.items.present? &amp;&amp; \n                order.payment_info.present?\n\n  # \u6ce8\u6587\u51e6\u7406\nend<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>\u914d\u5217\u51e6\u7406\u3067\u306e\u6d3b\u7528\uff1a<\/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=\"\">def bulk_process(records)\n  valid_records = records.select(&amp;:present?)\n  processed_data = valid_records.map do |record|\n    process_record(record) if record.data.present?\n  end.compact\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u3053\u308c\u3089\u306e\u4f8b\u3067\u793a\u3057\u305f\u3088\u3046\u306b\u3001present\u30e1\u30bd\u30c3\u30c9\u306f\u69d8\u3005\u306a\u30b7\u30c1\u30e5\u30a8\u30fc\u30b7\u30e7\u30f3\u3067\u6d3b\u7528\u3067\u304d\u3001\u30b3\u30fc\u30c9\u306e\u53ef\u8aad\u6027\u3068\u4fdd\u5b88\u6027\u3092\u5411\u4e0a\u3055\u305b\u308b\u5f37\u529b\u306a\u30c4\u30fc\u30eb\u3068\u306a\u308a\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-7\">present\u30e1\u30bd\u30c3\u30c9\u3092\u4f7f\u3063\u305f\u653b\u7565\u30c6\u30af\u30cb\u30c3\u30af<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-8\">\u30e1\u30bd\u30c3\u30c9\u30c1\u30a7\u30fc\u30f3\u3067\u306epresent\u30e1\u30bd\u30c3\u30c9\u306e\u6d3b\u7528<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u30e1\u30bd\u30c3\u30c9\u30c1\u30a7\u30fc\u30f3\u3067present\u30e1\u30bd\u30c3\u30c9\u3092\u52b9\u679c\u7684\u306b\u4f7f\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u30a8\u30ec\u30ac\u30f3\u30c8\u3067\u4fdd\u5b88\u6027\u306e\u9ad8\u3044\u30b3\u30fc\u30c9\u3092\u66f8\u304f\u3053\u3068\u304c\u3067\u304d\u307e\u3059\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=\"\"># \u57fa\u672c\u7684\u306a\u30e1\u30bd\u30c3\u30c9\u30c1\u30a7\u30fc\u30f3\u306e\u4f8b\nclass ArticleService\n  def featured_articles\n    Article.active\n           .where(featured: true)\n           .includes(:author)\n           .select { |article| article.author.present? }\n           .select { |article| article.content.present? }\n  end\n\n  # \u3088\u308a\u6d17\u7df4\u3055\u308c\u305f\u4f7f\u7528\u4f8b\n  def process_articles\n    Article.active\n           .tap { |articles| log_processing(articles) if articles.present? }\n           .map { |article| enrich_article(article) if article.present? }\n           .compact\n  end\n\n  # try + present\u306e\u7d44\u307f\u5408\u308f\u305b\n  def user_articles(user)\n    user.try(:articles)\n        .try(:active)\n        &amp;.select(&amp;:present?)\n        .presence || []\n  end\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u9ad8\u5ea6\u306a\u30c1\u30a7\u30fc\u30cb\u30f3\u30b0\u30c6\u30af\u30cb\u30c3\u30af\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=\"\">class DataProcessor\n  # \u8907\u6570\u306e\u6761\u4ef6\u3092\u7d44\u307f\u5408\u308f\u305b\u305f\u51e6\u7406\n  def process_data(data)\n    data.presence\n        &amp;.transform_keys(&amp;:to_sym)\n        &amp;.slice(*required_keys)\n        &amp;.tap { |d| validate_data(d) }\n        &amp;.transform_values { |v| process_value(v) if v.present? }\n  end\n\n  # Option\u578b\u306e\u3088\u3046\u306a\u4f7f\u3044\u65b9\n  def safe_process(data)\n    Result.new(\n      data.present? &amp;&amp; process_data(data).present?\n    )\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-9\">\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u3067\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">present\u30e1\u30bd\u30c3\u30c9\u3092\u4f7f\u7528\u3057\u305f\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u306e\u5b9f\u88c5\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=\"\">class User &lt; ApplicationRecord\n  validate :profile_completeness\n\n  private\n\n  # \u8907\u5408\u7684\u306a\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n  def profile_completeness\n    return if guest?\n\n    required_fields = [name, email, contact_number]\n    unless required_fields.all?(&amp;:present?)\n      errors.add(:base, \"\u30d7\u30ed\u30d5\u30a3\u30fc\u30eb\u306e\u5fc5\u9808\u9805\u76ee\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\")\n    end\n  end\nend\n\nclass Order &lt; ApplicationRecord\n  # \u30ab\u30b9\u30bf\u30e0\u30d0\u30ea\u30c7\u30fc\u30bf\u3067\u306e\u4f7f\u7528\n  class DetailsValidator &lt; ActiveModel::Validator\n    def validate(record)\n      return if record.draft?\n\n      validate_shipping_info(record)\n      validate_payment_info(record)\n    end\n\n    private\n\n    def validate_shipping_info(record)\n      unless record.shipping_address.present? &amp;&amp; \n             record.shipping_method.present?\n        record.errors.add(:base, \"\u914d\u9001\u60c5\u5831\u304c\u4e0d\u5b8c\u5168\u3067\u3059\")\n      end\n    end\n\n    def validate_payment_info(record)\n      return if record.payment_details.present? &amp;&amp;\n                record.payment_details.valid?\n\n      record.errors.add(:payment_details, \"\u652f\u6255\u3044\u60c5\u5831\u304c\u7121\u52b9\u3067\u3059\")\n    end\n  end\n\n  validates_with DetailsValidator\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-10\">\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3092\u8003\u616e\u3057\u305f\u4f7f\u7528\u65b9\u6cd5<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">present\u30e1\u30bd\u30c3\u30c9\u3092\u52b9\u7387\u7684\u306b\u4f7f\u7528\u3059\u308b\u305f\u3081\u306e\u30c6\u30af\u30cb\u30c3\u30af\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=\"\">class OptimizedDataProcessor\n  # \u65e9\u671f\u30ea\u30bf\u30fc\u30f3\u306b\u3088\u308b\u6700\u9069\u5316\n  def process_batch(records)\n    return [] unless records.present?\n\n    records.each_with_object([]) do |record, processed|\n      next unless record.present?\n\n      # \u51e6\u7406\u306e\u5b9f\u884c\n      processed &lt;&lt; process_single(record)\n    end\n  end\n\n  # \u30ad\u30e3\u30c3\u30b7\u30e5\u3068\u306e\u7d44\u307f\u5408\u308f\u305b\n  def cached_user_data(user_id)\n    Rails.cache.fetch(\"user_data\/#{user_id}\", expires_in: 1.hour) do\n      user = User.find_by(id: user_id)\n      return unless user.present?\n\n      {\n        name: user.name,\n        email: user.email,\n        preferences: user.preferences.presence || default_preferences\n      }\n    end\n  end\nend\n\n# \u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u6700\u9069\u5316\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\nclass PerformanceOptimizedService\n  # 1. \u8907\u6570\u56de\u306epresent?\u30c1\u30a7\u30c3\u30af\u3092\u907f\u3051\u308b\n  def bad_example(user)\n    return unless user.present?\n    return unless user.name.present?\n    return unless user.email.present?\n    # \u51e6\u7406\n  end\n\n  def good_example(user)\n    if user&amp;.name.present? &amp;&amp; user.email.present?\n      # \u51e6\u7406\n    end\n  end\n\n  # 2. \u5927\u898f\u6a21\u306a\u30b3\u30ec\u30af\u30b7\u30e7\u30f3\u51e6\u7406\u3067\u306e\u6700\u9069\u5316\n  def process_large_collection(collection)\n    return unless collection.present?\n\n    collection.find_each do |item|\n      process_item(item) if item.present?\n    end\n  end\n\n  # 3. presence + ||\u6f14\u7b97\u5b50\u306e\u52b9\u7387\u7684\u306a\u4f7f\u7528\n  def get_config\n    custom_config.presence || default_config\n  end\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u6700\u9069\u5316\u306e\u30dd\u30a4\u30f3\u30c8\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u4e0d\u8981\u306a\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30af\u30a8\u30ea\u306e\u56de\u907f<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>present?\u30c1\u30a7\u30c3\u30af\u524d\u306beager loading\u3092\u6d3b\u7528<\/li>\n\n\n\n<li>\u5fc5\u8981\u306a\u30ab\u30e9\u30e0\u306e\u307f\u3092\u9078\u629e<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30e1\u30e2\u30ea\u4f7f\u7528\u306e\u6700\u9069\u5316<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5927\u898f\u6a21\u306a\u30b3\u30ec\u30af\u30b7\u30e7\u30f3\u3067\u306efind_each\u306e\u4f7f\u7528<\/li>\n\n\n\n<li>\u5fc5\u8981\u306a\u5834\u5408\u306e\u307fpresent?\u30c1\u30a7\u30c3\u30af\u3092\u5b9f\u884c<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30ad\u30e3\u30c3\u30b7\u30e5\u306e\u52b9\u679c\u7684\u306a\u6d3b\u7528<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u983b\u7e41\u306b\u4f7f\u7528\u3055\u308c\u308b\u5b58\u5728\u30c1\u30a7\u30c3\u30af\u306e\u7d50\u679c\u3092\u30ad\u30e3\u30c3\u30b7\u30e5<\/li>\n\n\n\n<li>presence_in\u30e1\u30bd\u30c3\u30c9\u306e\u6d3b\u7528<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">\u3053\u308c\u3089\u306e\u30c6\u30af\u30cb\u30c3\u30af\u3092\u7d44\u307f\u5408\u308f\u305b\u308b\u3053\u3068\u3067\u3001\u52b9\u7387\u7684\u3067\u4fdd\u5b88\u6027\u306e\u9ad8\u3044\u30b3\u30fc\u30c9\u3092\u5b9f\u73fe\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-11\">\u3088\u304f\u3042\u308b\u30df\u30b9\u3068\u89e3\u6c7a\u7b56<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-12\">\u5b58\u5728 vs \u5b58\u5728\uff1a\u9069\u5207\u306a\u4f7f\u3044\u65b9<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">present\u30e1\u30bd\u30c3\u30c9\u306e\u4f7f\u7528\u306b\u304a\u3044\u3066\u3001\u3088\u304f\u898b\u3089\u308c\u308b\u8aa4\u308a\u3068\u305d\u306e\u89e3\u6c7a\u7b56\u3092\u898b\u3066\u3044\u304d\u307e\u3057\u3087\u3046\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=\"\"># \u8aa4\u3063\u305f\u4f7f\u7528\u4f8b1\uff1a\u4e0d\u8981\u306a\u4e8c\u91cd\u30c1\u30a7\u30c3\u30af\ndef process_user(user)\n  # \u4e0d\u8981\u306a\u4e8c\u91cd\u30c1\u30a7\u30c3\u30af\n  if user.present? &amp;&amp; !user.nil?  # \u5197\u9577\n    process_data(user)\n  end\nend\n\n# \u6b63\u3057\u3044\u4f7f\u7528\u4f8b1\ndef process_user(user)\n  return unless user.present?\n  process_data(user)\nend\n\n# \u8aa4\u3063\u305f\u4f7f\u7528\u4f8b2\uff1a\u5b58\u5728\u30c1\u30a7\u30c3\u30af\u306e\u9806\u5e8f\u304c\u975e\u52b9\u7387\ndef validate_order(order)\n  # nil\u306e\u53ef\u80fd\u6027\u304c\u3042\u308border\u304b\u3089items\u306b\u30a2\u30af\u30bb\u30b9\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u308b\n  if order.items.present? &amp;&amp; order.present?  # NoMethodError \u306e\u53ef\u80fd\u6027\n    process_order(order)\n  end\nend\n\n# \u6b63\u3057\u3044\u4f7f\u7528\u4f8b2\ndef validate_order(order)\n  return unless order.present? &amp;&amp; order.items.present?\n  process_order(order)\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u3088\u304f\u3042\u308b\u9593\u9055\u3044\u3068\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u5b58\u5728\u30c1\u30a7\u30c3\u30af\u306e\u91cd\u8907<\/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=\"\"># \u60aa\u3044\u4f8b\ndef process_data(data)\n  if data.present?\n    if !data.empty?  # \u5197\u9577\u306a\u30c1\u30a7\u30c3\u30af\n      process(data)\n    end\n  end\nend\n\n# \u826f\u3044\u4f8b\ndef process_data(data)\n  return unless data.present?\n  process(data)\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u4e0d\u9069\u5207\u306a\u30c1\u30a7\u30c3\u30af\u9806\u5e8f<\/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=\"\"># \u60aa\u3044\u4f8b\ndef process_user_settings(user)\n  if user.settings.present? &amp;&amp; user.present?\n    # user \u304c nil \u306e\u5834\u5408\u3001NoMethodError \u304c\u767a\u751f\n  end\nend\n\n# \u826f\u3044\u4f8b\ndef process_user_settings(user)\n  return unless user.present? &amp;&amp; user.settings.present?\n  # \u5b89\u5168\u306b\u51e6\u7406\u3092\u5b9f\u884c\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-13\">nil\u5bfe\u7b56\u3068\u30a8\u30e9\u30fc\u56de\u907f\u306e\u30c6\u30af\u30cb\u30c3\u30af<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">nil\u306b\u3088\u308b\u30a8\u30e9\u30fc\u3092\u9632\u3050\u305f\u3081\u306e\u52b9\u679c\u7684\u306a\u30c6\u30af\u30cb\u30c3\u30af\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=\"\">class DataProcessor\n  # \u30bb\u30fc\u30d5\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3\u6f14\u7b97\u5b50\u3068\u306e\u7d44\u307f\u5408\u308f\u305b\n  def process_user_data(user)\n    # \u5b89\u5168\u306a\u30a2\u30af\u30bb\u30b9\n    if user&amp;.profile&amp;.preferences.present?\n      process_preferences(user.profile.preferences)\n    end\n  end\n\n  # try \u30e1\u30bd\u30c3\u30c9\u3068\u306e\u7d44\u307f\u5408\u308f\u305b\n  def get_user_setting(user)\n    user.try(:settings)\n        .try(:general)\n        .presence || default_settings\n  end\n\n  # \u914d\u5217\u51e6\u7406\u3067\u306e\u5b89\u5168\u306a\u4f7f\u7528\n  def process_items(items)\n    # \u30b3\u30f3\u30d1\u30af\u30c8\u306a\u51e6\u7406\n    Array(items).select(&amp;:present?).each do |item|\n      process_single_item(item)\n    end\n  end\nend\n\n# \u30a8\u30e9\u30fc\u56de\u907f\u306e\u305f\u3081\u306e\u30e6\u30fc\u30c6\u30a3\u30ea\u30c6\u30a3\u30e1\u30bd\u30c3\u30c9\nmodule SafeAccessor\n  def safe_dig(object, *keys)\n    keys.inject(object) do |obj, key|\n      return unless obj.present?\n      obj.try(key)\n    end\n  end\nend\n\nclass ApplicationController\n  include SafeAccessor\n\n  def process_params\n    # \u30d1\u30e9\u30e1\u30fc\u30bf\u306e\u5b89\u5168\u306a\u53d6\u5f97\n    user_id = safe_dig(params, :user, :id)\n    return unless user_id.present?\n\n    process_user(user_id)\n  end\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u30a8\u30e9\u30fc\u9632\u6b62\u306e\u305f\u3081\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30c7\u30d5\u30a9\u30eb\u30c8\u5024\u306e\u9069\u5207\u306a\u4f7f\u7528<\/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 Configuration\n  def get_setting(key)\n    settings.dig(key).presence || default_for(key)\n  end\n\n  private\n\n  def default_for(key)\n    case key\n    when :timeout then 30\n    when :retries then 3\n    else nil\n    end\n  end\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u6761\u4ef6\u5206\u5c90\u3067\u306e\u9069\u5207\u306a\u4f7f\u7528<\/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 UserService\n  def update_profile(user, params)\n    return false unless user.present?\n\n    # \u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u3067\u306e\u4f7f\u7528\n    User.transaction do\n      if params[:profile_attributes].present?\n        user.profile.update!(params[:profile_attributes])\n      end\n\n      if params[:settings_attributes].present?\n        user.settings.update!(params[:settings_attributes])\n      end\n    end\n\n    true\n  rescue ActiveRecord::RecordInvalid\n    false\n  end\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u3053\u308c\u3089\u306e\u5bfe\u7b56\u3092\u5b9f\u88c5\u3059\u308b\u3053\u3068\u3067\u3001\u3088\u308a\u5805\u7262\u306a\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u69cb\u7bc9\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-14\">\u5b9f\u52d9\u3067\u306e\u5fdc\u7528\u3068\u767a\u5c55\u7684\u306a\u4f7f\u3044\u65b9<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-15\">\u5927\u898f\u6a21\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306e\u6d3b\u7528\u4e8b\u4f8b<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u5927\u898f\u6a21\u306aRails\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306epresent\u30e1\u30bd\u30c3\u30c9\u306e\u52b9\u679c\u7684\u306a\u6d3b\u7528\u65b9\u6cd5\u3092\u898b\u3066\u3044\u304d\u307e\u3057\u3087\u3046\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=\"\"># \u30b5\u30fc\u30d3\u30b9\u30af\u30e9\u30b9\u3067\u306e\u6d3b\u7528\nclass OrderProcessingService\n  include ActiveModel::Validations\n\n  def initialize(order)\n    @order = order\n    @errors = []\n  end\n\n  def process\n    return ServiceResult.error('\u7121\u52b9\u306a\u6ce8\u6587\u3067\u3059') unless valid_order?\n\n    OrderProcessor.transaction do\n      process_payment\n      update_inventory\n      send_notifications\n    end\n\n    ServiceResult.success('\u6ce8\u6587\u51e6\u7406\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f')\n  rescue =&gt; e\n    ServiceResult.error(\"\u51e6\u7406\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f: #{e.message}\")\n  end\n\n  private\n\n  def valid_order?\n    @order.present? &amp;&amp;\n      @order.items.present? &amp;&amp;\n      @order.payment_details.present? &amp;&amp;\n      @order.shipping_address.present?\n  end\n\n  def process_payment\n    return unless @order.payment_details.present?\n    PaymentProcessor.new(@order).process\n  end\n\n  def update_inventory\n    @order.items.select(&amp;:present?).each do |item|\n      InventoryManager.update_stock(item)\n    end\n  end\n\n  def send_notifications\n    NotificationDispatcher.new(@order).dispatch if @order.user.present?\n  end\nend\n\n# \u5024\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30d1\u30bf\u30fc\u30f3\u3067\u306e\u6d3b\u7528\nclass Money\n  include Comparable\n\n  attr_reader :amount, :currency\n\n  def initialize(amount, currency = 'JPY')\n    @amount = amount\n    @currency = currency\n  end\n\n  def present?\n    amount.present? &amp;&amp; amount.positive?\n  end\n\n  def &lt;=&gt;(other)\n    return unless other.present? &amp;&amp; compatible?(other)\n    amount &lt;=&gt; other.amount\n  end\n\n  private\n\n  def compatible?(other)\n    currency == other.currency\n  end\nend\n\n# Concern\u3067\u306e\u5171\u901a\u6a5f\u80fd\u5b9f\u88c5\nmodule Trackable\n  extend ActiveSupport::Concern\n\n  included do\n    before_save :track_changes, if: :tracked_attributes_changed?\n  end\n\n  def tracked_attributes_changed?\n    tracked_attributes.any? do |attr|\n      send(attr).present? &amp;&amp; send(\"#{attr}_changed?\")\n    end\n  end\n\n  private\n\n  def track_changes\n    return unless changes.present?\n\n    tracked_changes = changes.select { |k, v| tracked_attributes.include?(k.to_sym) }\n    create_audit_log(tracked_changes) if tracked_changes.present?\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-16\">\u30ab\u30b9\u30bf\u30e0\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u3067\u306e\u7d44\u307f\u8fbc\u307f\u65b9<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u8907\u96d1\u306a\u30d3\u30b8\u30cd\u30b9\u30ed\u30b8\u30c3\u30af\u3092\u542b\u3080\u30ab\u30b9\u30bf\u30e0\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u306e\u5b9f\u88c5\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=\"\"># \u30ab\u30b9\u30bf\u30e0\u30d0\u30ea\u30c7\u30fc\u30bf\u306e\u5b9f\u88c5\nclass SubscriptionValidator &lt; ActiveModel::Validator\n  def validate(record)\n    return unless record.present?\n\n    validate_plan(record)\n    validate_payment_method(record)\n    validate_billing_period(record)\n  end\n\n  private\n\n  def validate_plan(record)\n    return if record.plan.present? &amp;&amp; record.plan.active?\n    record.errors.add(:plan, '\u6709\u52b9\u306a\u30d7\u30e9\u30f3\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044')\n  end\n\n  def validate_payment_method(record)\n    return if record.payment_method.present? &amp;&amp; \n              record.payment_method.valid_for_plan?(record.plan)\n    record.errors.add(:payment_method, '\u6709\u52b9\u306a\u652f\u6255\u65b9\u6cd5\u3092\u8a2d\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044')\n  end\n\n  def validate_billing_period(record)\n    return if record.billing_period.present? &amp;&amp; \n              record.plan.available_periods.include?(record.billing_period)\n    record.errors.add(:billing_period, '\u9069\u5207\u306a\u8acb\u6c42\u671f\u9593\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044')\n  end\nend\n\n# \u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u6a5f\u80fd\u306e\u62e1\u5f35\nmodule CustomValidations\n  extend ActiveSupport::Concern\n\n  included do\n    include ActiveModel::Validations\n  end\n\n  class_methods do\n    def validates_presence_of_all(*attrs)\n      attrs.each do |attr|\n        validate do |record|\n          value = record.send(attr)\n          record.errors.add(attr, :blank) unless value.present?\n        end\n      end\n    end\n  end\nend\n\n# \u5b9f\u88c5\u4f8b\nclass Subscription &lt; ApplicationRecord\n  include CustomValidations\n\n  belongs_to :user\n  belongs_to :plan\n  has_one :payment_method\n\n  validates_with SubscriptionValidator\n  validates_presence_of_all :user, :plan, :payment_method, :billing_period\n\n  # \u30ab\u30b9\u30bf\u30e0\u30b9\u30b3\u30fc\u30d7\n  scope :active_with_valid_payment, -&gt; {\n    joins(:payment_method)\n      .where(active: true)\n      .select { |sub| sub.payment_method.present? &amp;&amp; sub.payment_method.valid? }\n  }\n\n  # \u30d3\u30b8\u30cd\u30b9\u30ed\u30b8\u30c3\u30af\n  def can_upgrade_to?(new_plan)\n    return false unless new_plan.present?\n\n    current_plan_index = Plan.pricing_order.index(plan)\n    new_plan_index = Plan.pricing_order.index(new_plan)\n\n    new_plan_index.present? &amp;&amp; new_plan_index &gt; current_plan_index\n  end\n\n  def process_renewal\n    return false unless valid_for_renewal?\n\n    begin\n      process_payment\n      extend_subscription_period\n      notify_renewal_success\n      true\n    rescue =&gt; e\n      notify_renewal_failure(e)\n      false\n    end\n  end\n\n  private\n\n  def valid_for_renewal?\n    active? &amp;&amp; \n    plan.present? &amp;&amp; \n    payment_method.present? &amp;&amp; \n    payment_method.valid?\n  end\nend<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">\u3053\u308c\u3089\u306e\u5b9f\u88c5\u4f8b\u306f\u3001present\u30e1\u30bd\u30c3\u30c9\u3092\u6d3b\u7528\u3057\u305f\u5b9f\u52d9\u7684\u306a\u30a2\u30d7\u30ed\u30fc\u30c1\u3092\u793a\u3057\u3066\u3044\u307e\u3059\u3002\u5927\u898f\u6a21\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306f\u3001\u3053\u306e\u3088\u3046\u306a\u9069\u5207\u306a\u62bd\u8c61\u5316\u3068\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u306e\u7d44\u307f\u5408\u308f\u305b\u304c\u3001\u4fdd\u5b88\u6027\u306e\u9ad8\u3044\u30b3\u30fc\u30c9\u30d9\u30fc\u30b9\u306e\u5b9f\u73fe\u306b\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":["post-1495","post","type-post","status-publish","format-standard","category-ruby","nothumb"],"_links":{"self":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/1495","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=1495"}],"version-history":[{"count":1,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/1495\/revisions"}],"predecessor-version":[{"id":1496,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/1495\/revisions\/1496"}],"wp:attachment":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1495"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1495"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1495"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}