{"id":598,"date":"2024-05-31T00:00:00","date_gmt":"2024-05-30T15:00:00","guid":{"rendered":"https:\/\/blog.fundely.co.jp\/tech\/?p=598"},"modified":"2024-05-31T13:40:25","modified_gmt":"2024-05-31T04:40:25","slug":"%e3%82%b3%e3%83%bc%e3%83%89%e3%81%ae%e6%95%b4%e7%90%86%e3%81%a8%e6%94%b9%e5%96%84","status":"publish","type":"post","link":"https:\/\/blog.fundely.co.jp\/tech\/2024\/05\/31\/%e3%82%b3%e3%83%bc%e3%83%89%e3%81%ae%e6%95%b4%e7%90%86%e3%81%a8%e6%94%b9%e5%96%84\/","title":{"rendered":"\u30b3\u30fc\u30c9\u306e\u6574\u7406\u3068\u6539\u5584"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"386\" src=\"https:\/\/blog.fundely.co.jp\/tech\/wp-content\/uploads\/sites\/2\/2024\/05\/xjonwqkmqpigf0f9ogp8_ws2.jpg\" alt=\"\" class=\"wp-image-622\" style=\"width:840px;height:auto\" srcset=\"https:\/\/blog.fundely.co.jp\/tech\/wp-content\/uploads\/sites\/2\/2024\/05\/xjonwqkmqpigf0f9ogp8_ws2.jpg 640w, https:\/\/blog.fundely.co.jp\/tech\/wp-content\/uploads\/sites\/2\/2024\/05\/xjonwqkmqpigf0f9ogp8_ws2-300x181.jpg 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">\u306f\u3058\u3081\u306b<\/h2>\n\n\n\n<p>\u5f0a\u793e\u3067\u306f\u4e3b\u529b\u30b5\u30fc\u30d3\u30b9\u3067\u3042\u308b\u300c\u30df\u30fc\u30eb\u30bf\u30a4\u30e0\u300d\u3084\u300c\u65ec\u3059\u3050\u300d\u306e\u958b\u767a\u306bRuby on Rails\u3092\u4f7f\u7528\u3057\u3066\u3044\u307e\u3059\u3002Rails\u306f\u975e\u5e38\u306b\u751f\u7523\u6027\u306e\u9ad8\u3044\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u3067\u3059\u304c\u3001\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u304c\u5927\u898f\u6a21\u5316\u3059\u308b\u306b\u3064\u308c\u3066\u3001\u30b3\u30fc\u30c9\u306e\u69cb\u9020\u3084\u8a2d\u8a08\u306b\u554f\u984c\u304c\u751f\u3058\u308b\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u4eca\u56de\u306f\u3001\u4ee5\u4e0b\u306b\u5bfe\u3057\u3066\u3069\u306e\u3088\u3046\u306b\u30a2\u30d7\u30ed\u30fc\u30c1\u3057\u3066\u3044\u308b\u304b\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Fat Controller<\/li>\n\n\n\n<li>\u8cac\u52d9\u306e\u5206\u96e2<\/li>\n\n\n\n<li>View\u306e\u30ed\u30b8\u30c3\u30af<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Fat Controller\u554f\u984c\u3078\u306e\u5bfe\u51e6<\/h2>\n\n\n\n<p>Rails\u3067\u306f\u300cSkinny Controller, Fat Model\u300d\u306e\u539f\u5247\u306b\u5f93\u3044\u3001\u30d3\u30b8\u30cd\u30b9\u30ed\u30b8\u30c3\u30af\u306f\u306a\u308b\u3079\u304f\u30e2\u30c7\u30eb\u306b\u5bc4\u305b\u3001\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u306f\u30ea\u30af\u30a8\u30b9\u30c8\u306e\u53d7\u3051\u53d6\u308a\u3068\u30ec\u30b9\u30dd\u30f3\u30b9\u306e\u8fd4\u5374\u306b\u5c02\u5ff5\u3059\u308b\u3053\u3068\u304c\u63a8\u5968\u3055\u308c\u3066\u3044\u307e\u3059\u3002<br>\u5f0a\u793e\u3067\u306f\u3001\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u306b\u66f8\u304b\u308c\u3066\u3044\u305f\u51e6\u7406\u3092\u3001\u30e2\u30c7\u30eb\u3084\u30b5\u30fc\u30d3\u30b9\u30af\u30e9\u30b9\u3001\u30e2\u30b8\u30e5\u30fc\u30eb\u3068\u3057\u3066\u5207\u308a\u51fa\u3059\u3088\u3046\u306b\u3057\u3066\u3044\u307e\u3059\u3002\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u5185\u3067\u306f\u3001\u4e3b\u306b\u3053\u308c\u3089\u306e\u30e2\u30c7\u30eb\u3084\u30e2\u30b8\u30e5\u30fc\u30eb\u3001\u30b5\u30fc\u30d3\u30b9\u30af\u30e9\u30b9\u3092\u547c\u3073\u51fa\u3059\u51e6\u7406\u3068\u30ec\u30b9\u30dd\u30f3\u30b9\u306e\u8a18\u8ff0\u3092\u884c\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code># \u5909\u66f4\u524d\n# app\/controllers\/orders_controller.rb\nclass OrdersController &lt; ApplicationController\n  def create\n    @order = Order.new(order_params)\n    @order.user = current_user\n    @order.total_price = calculate_total_price(@order)\n    \n    if @order.save\n      @order.line_items.each do |line_item|\n        product = line_item.product\n        product.decrement!(:stock_quantity, line_item.quantity)\n      end\n      \n      OrderMailer.confirmation_email(@order).deliver_now\n      redirect_to @order, notice: &#39;Order was successfully created.&#39;\n    else\n      render :new\n    end\n  end\n\n  private\n\n  def order_params\n    params.require(:order).permit(:shipping_address, line_items_attributes: [:product_id, :quantity])\n  end\n\n  def calculate_total_price(order)\n    order.line_items.sum { |line_item| line_item.product.price * line_item.quantity }\n  end\nend\n\n# \u5909\u66f4\u5f8c \n# app\/controllers\/orders_controller.rb\nclass OrdersController &lt; ApplicationController\n  def create\n    @order = current_user.orders.build(order_params)\n    \n    if @order.save\n      redirect_to @order, notice: &#39;Order was successfully created.&#39;\n    else\n      render :new\n    end\n  end\n\n  private\n\n  def order_params\n    params.require(:order).permit(:shipping_address, line_items_attributes: [:product_id, :quantity])\n  end\nend\n\n# app\/models\/order.rb\nclass Order &lt; ActiveRecord::Base\n  belongs_to :user\n  has_many :line_items\n  accepts_nested_attributes_for :line_items\n\n  before_save :calculate_total_price\n  after_create :update_product_stock\n  after_create :send_confirmation_email\n\n  private\n\n  def calculate_total_price\n    self.total_price = line_items.sum { |line_item| line_item.product.price * line_item.quantity }\n  end\n\n  def update_product_stock\n    line_items.each do |line_item|\n      product = line_item.product\n      product.decrement!(:stock_quantity, line_item.quantity)\n    end\n  end\n\n  def send_confirmation_email\n    OrderMailer.confirmation_email(self).deliver_now\n  end\nend<\/code><\/pre><\/div>\n\n\n\n<p>\u4e0a\u8a18\u306e\u4f8b\u3067\u306f\u3001\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u304b\u3089\u30e2\u30c7\u30eb\u3078\u51e6\u7406\u3092\u79fb\u52d5\u3057\u3001\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u3092\u30b9\u30ea\u30e0\u5316\u3057\u3066\u3044\u307e\u3059\u3002calculate_total_price\u3001update_product_stock\u3001send_confirmation_email\u3068\u3044\u3063\u305f\u51e6\u7406\u3092\u30e2\u30c7\u30eb\u306e\u30b3\u30fc\u30eb\u30d0\u30c3\u30af\u3068\u3057\u3066\u5b9a\u7fa9\u3059\u308b\u3053\u3068\u3067\u3001\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u306e\u8cac\u52d9\u3092\u660e\u78ba\u306b\u3057\u3066\u3044\u307e\u3059\u3002\uff08\u5b9f\u969b\u306e\u73fe\u5834\u3067\u306f\u3001before_save\u3084after_create\u306a\u3069\u306e\u30b3\u30fc\u30eb\u30d0\u30c3\u30af\u306f\u3042\u307e\u308a\u4f7f\u7528\u3057\u3066\u3044\u307e\u305b\u3093\uff09<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u8cac\u52d9\u306e\u5206\u96e2<\/h2>\n\n\n\n<p>\u73fe\u5728\u306e\u672c\u756a\u30b3\u30fc\u30c9\u306f\u30e2\u30c7\u30eb\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u30e1\u30bd\u30c3\u30c9\u3084\u30af\u30e9\u30b9\u30e1\u30bd\u30c3\u30c9\u304c\u80a5\u5927\u5316\u3057\u904e\u304e\u3066\u304a\u308a\u3001\u5225\u30e2\u30c7\u30eb\u306e\u64cd\u4f5c\u307e\u3067\u884c\u3063\u3066\u3044\u308b\u30b1\u30fc\u30b9\u3082\u5b58\u5728\u3057\u3066\u3044\u307e\u3059\u3002\u3053\u308c\u3089\u306b\u5bfe\u3057\u3001\u9069\u5207\u306a\u5206\u5272\u3068\u5358\u4e00\u8cac\u4efb\u306e\u539f\u5247\u306b\u5f93\u3046\u3088\u3046\u306b\u30ea\u30d5\u30a1\u30af\u30bf\u30ea\u30f3\u30b0\u3092\u884c\u3063\u3066\u3044\u307e\u3059\u3002\u307e\u305f\u3001\u8907\u6570\u306e\u30e2\u30c7\u30eb\u306b\u307e\u305f\u304c\u308b\u51e6\u7406\u306f\u4e00\u5ea6\u30b5\u30fc\u30d3\u30b9\u30af\u30e9\u30b9\u306b\u5207\u308a\u5206\u3051\u308b\u3088\u3046\u306b\u3057\u3066\u3044\u307e\u3059\u3002\u30b5\u30fc\u30d3\u30b9\u30af\u30e9\u30b9\u3092\u4f5c\u6210\u3059\u308b\u3053\u3068\u3067\u3001\u5f71\u97ff\u7bc4\u56f2\u3084\u696d\u52d9\u624b\u7d9a\u304d\u304c\u308f\u304b\u308a\u3084\u3059\u304f\u306a\u308a\u307e\u3059\u3002\u305d\u306e\u5f8c\u3001\u5fc5\u8981\u3067\u3042\u308c\u3070\u9069\u3057\u305f\u7c92\u5ea6\u306b\u518d\u5ea6\u30ea\u30d5\u30a1\u30af\u30bf\u30ea\u30f3\u30b0\u3092\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code># \u5909\u66f4\u524d\nclass User &lt; ActiveRecord::Base\n  def self.import_csv(file)\n    CSV.foreach(file.path, headers: true) do |row|\n      user = find_by(email: row[&quot;email&quot;]) || new\n      user.attributes = row.to_hash.slice(*updatable_attributes)\n      user.save!\n    end\n  end\nend\n\n# \u5909\u66f4\u5f8c\nmodule Concerns::Service\n  extend ActiveSupport::Concern\nend\n\nclass User::CsvImportService\n  include Concerns::Service\n\n  def initialize(file: nil)\n    @file = file\n  end\n\n  def call\n    CSV.foreach(file.path, headers: true) do |row|\n      user = User.find_by(email: row[&quot;email&quot;]) || User.new\n      user.attributes = row.to_hash.slice(*User.updatable_attributes)\n      user.save!\n    end\n  end\nend<\/code><\/pre><\/div>\n\n\n\n<p>\u4e0a\u8a18\u306e\u4f8b\u3067\u306f\u3001User\u30e2\u30c7\u30eb\u304b\u3089import_csv\u30e1\u30bd\u30c3\u30c9\u3092\u5207\u308a\u51fa\u3057\u3001User::CsvImportService\u3068\u3044\u3046\u30b5\u30fc\u30d3\u30b9\u30af\u30e9\u30b9\u3092\u4f5c\u6210\u3057\u3066\u3044\u307e\u3059\u3002\u3053\u308c\u306b\u3088\u308a\u3001User\u30e2\u30c7\u30eb\u306e\u8cac\u52d9\u3092\u660e\u78ba\u306b\u3057\u3001CSV\u30a4\u30f3\u30dd\u30fc\u30c8\u306e\u51e6\u7406\u3092\u72ec\u7acb\u3057\u305f\u30af\u30e9\u30b9\u3067\u7ba1\u7406\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">View\u306e\u30ed\u30b8\u30c3\u30af<\/h2>\n\n\n\n<p>View\u306b\u30ed\u30b8\u30c3\u30af\u304c\u66f8\u304b\u308c\u3066\u3044\u308b\u5834\u5408\u306f\u3001\u30d8\u30eb\u30d1\u30fc\u30e1\u30bd\u30c3\u30c9\u3092\u4f7f\u7528\u3059\u308b\u3088\u3046\u306b\u30ea\u30d5\u30a1\u30af\u30bf\u30ea\u30f3\u30b0\u3057\u3066\u3044\u307e\u3059\u3002\u307e\u305f\u3001\u30d5\u30a9\u30fc\u30e0\u306b\u95a2\u3057\u3066\u306f\u6975\u529b\u30d5\u30a9\u30fc\u30e0\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u30d1\u30bf\u30fc\u30f3\u3092\u4f7f\u7528\u3059\u308b\u3088\u3046\u306b\u5909\u66f4\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>&lt;!-- \u5909\u66f4\u524d --&gt;\n&lt;% if current_user.admin? || current_user == @post.user %&gt;\n  &lt;%= link_to &#39;\u7de8\u96c6&#39;, edit_post_path(@post) %&gt;\n  &lt;%= link_to &#39;\u524a\u9664&#39;, post_path(@post), method: :delete, data: { confirm: &#39;\u672c\u5f53\u306b\u524a\u9664\u3057\u307e\u3059\u304b\uff1f&#39; } %&gt;\n&lt;% end %&gt;\n\n&lt;!-- \u5909\u66f4\u5f8c --&gt;\n&lt;% if policy(@post).edit? %&gt;\n  &lt;%= link_to &#39;\u7de8\u96c6&#39;, edit_post_path(@post) %&gt;\n&lt;% end %&gt;\n&lt;% if policy(@post).destroy? %&gt;  \n  &lt;%= link_to &#39;\u524a\u9664&#39;, post_path(@post), method: :delete, data: { confirm: &#39;\u672c\u5f53\u306b\u524a\u9664\u3057\u307e\u3059\u304b\uff1f&#39; } %&gt;\n&lt;% end %&gt;<\/code><\/pre><\/div>\n\n\n\n<p>\u4e0a\u8a18\u306e\u4f8b\u3067\u306f\u3001View\u306e\u6761\u4ef6\u5206\u5c90\u3092\u30dd\u30ea\u30b7\u30fc\u30af\u30e9\u30b9\u3092\u4f7f\u7528\u3057\u3066\u7f6e\u304d\u63db\u3048\u3066\u3044\u307e\u3059\u3002\u3053\u308c\u306b\u3088\u308a\u3001\u6a29\u9650\u30c1\u30a7\u30c3\u30af\u306e\u30ed\u30b8\u30c3\u30af\u3092View\u304b\u3089\u5206\u96e2\u3057\u3001\u30b3\u30fc\u30c9\u306e\u53ef\u8aad\u6027\u3068\u4fdd\u5b88\u6027\u3092\u5411\u4e0a\u3055\u305b\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u307e\u3068\u3081<\/h2>\n\n\n\n<p>\u5f0a\u793e\u3067\u306f\u4e0a\u8a18\u306e\u3088\u3046\u306a\u30a2\u30d7\u30ed\u30fc\u30c1\u3067Rails\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30b3\u30fc\u30c9\u54c1\u8cea\u6539\u5584\u306b\u53d6\u308a\u7d44\u3093\u3067\u3044\u307e\u3059\u3002\u3082\u3061\u308d\u3093\u3001\u3053\u308c\u3089\u306f\u4e00\u671d\u4e00\u5915\u306b\u3067\u304d\u308b\u3082\u306e\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u30ea\u30d5\u30a1\u30af\u30bf\u30ea\u30f3\u30b0\u306f\u6bb5\u968e\u7684\u306b\u884c\u3044\u3001\u30c6\u30b9\u30c8\u3092\u66f8\u304d\u306a\u304c\u3089\u9032\u3081\u3066\u3044\u304f\u3053\u3068\u304c\u91cd\u8981\u3060\u3068\u8003\u3048\u3066\u3044\u307e\u3059\u3002\u4eca\u5f8c\u3082\u30b5\u30fc\u30d3\u30b9\u306e\u6210\u9577\u306b\u5408\u308f\u305b\u3066\u3001\u7d99\u7d9a\u7684\u306b\u30b3\u30fc\u30c9\u306e\u6539\u5584\u3092\u884c\u3063\u3066\u3044\u304d\u305f\u3044\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button aligncenter is-style-fill\"><a class=\"wp-block-button__link has-vivid-green-cyan-background-color has-background wp-element-button\" href=\"https:\/\/blog.fundely.co.jp\/tech\/?page_id=82&amp;preview=true\" style=\"border-radius:12px\">\u52df\u96c6\u8981\u9805\u304a\u3088\u3073\u30a8\u30f3\u30c8\u30ea\u30fc\u30d5\u30a9\u30fc\u30e0<\/a><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u306f\u3058\u3081\u306b \u5f0a\u793e\u3067\u306f\u4e3b\u529b\u30b5\u30fc\u30d3\u30b9\u3067\u3042\u308b\u300c\u30df\u30fc\u30eb\u30bf\u30a4\u30e0\u300d\u3084\u300c\u65ec\u3059\u3050\u300d\u306e\u958b\u767a\u306bRuby on Rails\u3092\u4f7f\u7528\u3057\u3066\u3044\u307e\u3059\u3002Rails\u306f\u975e\u5e38\u306b\u751f\u7523\u6027\u306e\u9ad8\u3044\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u3067\u3059\u304c\u3001\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u304c\u5927\u898f\u6a21\u5316\u3059\u308b\u306b\u3064\u308c\u3066\u3001\u30b3\u30fc\u30c9\u306e\u69cb\u9020\u3084\u8a2d [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3,17,1],"tags":[],"class_list":["post-598","post","type-post","status-publish","format-standard","hentry","category-rails","category-ruby","category-uncategorized"],"acf":[],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/blog.fundely.co.jp\/tech\/wp-json\/wp\/v2\/posts\/598","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.fundely.co.jp\/tech\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.fundely.co.jp\/tech\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.fundely.co.jp\/tech\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.fundely.co.jp\/tech\/wp-json\/wp\/v2\/comments?post=598"}],"version-history":[{"count":22,"href":"https:\/\/blog.fundely.co.jp\/tech\/wp-json\/wp\/v2\/posts\/598\/revisions"}],"predecessor-version":[{"id":623,"href":"https:\/\/blog.fundely.co.jp\/tech\/wp-json\/wp\/v2\/posts\/598\/revisions\/623"}],"wp:attachment":[{"href":"https:\/\/blog.fundely.co.jp\/tech\/wp-json\/wp\/v2\/media?parent=598"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.fundely.co.jp\/tech\/wp-json\/wp\/v2\/categories?post=598"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.fundely.co.jp\/tech\/wp-json\/wp\/v2\/tags?post=598"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}