【Ruby on rails6】「jp_prefecture」と「jpostal」を使って住所を自動で入力するフォームを作成する

【Ruby on rails6】「jp_prefecture」と「jpostal」を使って住所を自動で入力するフォームを作成する

今回はjp_prefectureとjpostalを使って郵便番号などを入力すると、その郵便番号に応じた住所を入力してくれるという機能を作っていきます。

1.Gemのインストール

gem 'jp_prefecture'
bundle install

2.jpostalを導入

application.html.erbの中にjpostalを使用するための記述を追加します。

<script type="text/javascript" src="//jpostal-1006.appspot.com/jquery.jpostal.js"></script>

javascript/packsの中のapplication.jsの中に以下の記述をします。

import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
import "jquery"
import "popper.js"
import "bootstrap"
import '@fortawesome/fontawesome-free/js/all';
import "../stylesheets/application" 

Rails.start()
Turbolinks.start()
ActiveStorage.start()

jQuery(document).on("turbolinks:load", function() {
  $('#user_postcode').jpostal({
    postcode : [
      // 取得する郵便番号のテキストボックスをidで指定
      '#user_postcode'
    ],
    address: {
      // %3 => 都道府県、 %4 => 市区町村 %5 => 町域 %6 => 番地 %7 => 名称
      // それぞれを表示するコントロールをidで指定
      "#user_prefecture_code"  : "%3",
      "#user_address_city"   : "%4%5",
      "#user_address_street" : "%6%7"
    }
  });
});

これでプラグインの導入が完了しました。

3.カラムを追加する

今あるユーザーモデルには住所などのカラムがないので、それを追加していきます。

      t.integer :postcode
      t.integer :prefecture_code
      t.string :address_city
      t.string :address_street
      t.string :address_building

このように住所に関することを記述して、migrateをやり直します。

4.モデルファイルの編集

include JpPrefecture
jp_prefecture :prefecture_code

この記述は都道府県コードから都道府県名に自動で変換するものです。

def prefecture_name
  JpPrefecture::Prefecture.find(code: prefecture_code).try(:name)
end

def prefecture_name=(prefecture_name)
  self.prefecture_code = JpPrefecture::Prefecture.find(name: prefecture_name).code
end

これはヘルパーメソッドで、~.prefecture_nameとすることで、簡単に都道府県名を参照できるようになります。

5.ストロングパラメータの編集

def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:email, :name, :postcode,
      :prefecture_code, :address_city, :address_street, :address_building])
  end

6.viewの編集

        <div class="field">
          <%= f.label :postcode, '郵便番号' %>
          <%= f.text_field :postcode, autocomplete: 'postcode', class: 'form-control' %>
        </div>
        <div class="field">
          <%= f.label :prefecture_name, '都道府県' %>
          <%= f.collection_select :prefecture_code, JpPrefecture::Prefecture.all, :code, :name, { prompt: '選択してください' }, class: 'form-control' %>
        </div>
        <div class="field">
          <%= f.label :address_city, '市区町村' %>
          <%= f.text_field :address_city, autocomplete: 'address_city', class: 'form-control' %>
        </div>
        <div class="field">
          <%= f.label :address_street, '番地' %>
          <%= f.text_field :address_street, autocomplete: 'address_street', class: 'form-control' %>
        </div>
        <div class="field">
          <%= f.label :address_building, '建物' %>
          <%= f.text_field :address_building, autocomplete: 'address_building', class: 'form-control' %>
        </div>

ここで注目するべきなのはprefecture_nameのところです。ここでは都道府県を全て入手し、それをcollection_selectで表示させるようにしています。

これで住所の自動入力は完成したので、動きを見てみましょう。

いい感じです!

7.他のviewの編集

今度は編集画面や詳細画面などの編集を一気にやっていきます。

def user_params
    params.require(:user).permit(:name, :introduction, :profile_image, :postcode,
      :prefecture_code, :address_city, :address_street, :address_building)
  end
def join_address
    "#{self.prefecture_name}#{self.address_city}#{self.address_street}#{self.address_building}"
  end

住所をまとめて表示できるメソッドを定義しました。

<table class='table'>
  <tr><%= image_tag user.get_profile_image, size:'100x100' %></tr>
  <tr>
	  <th>名前</th>
	  <th><%= user.name %></th>
  </tr>
  <tr>
	  <th>自己紹介文</th>
	  <th><%= user.introduction %></th>
  </tr>
  <% if user == current_user %>
    <tr>
	    <th>メールアドレス</th>
	    <th><%= user.email %></th>
    </tr>
    <tr>
	    <th>郵便番号</th>
	    <th><%= user.postcode %></th>
    </tr>
    <tr>
      <th>住所</th>
      <th><%= user.join_address %></th>
    </tr>
  <% end %>
  <tr>
    <th>フォロー</th>
    <th><%= link_to user.followings.count, user_followings_path(user) %></th>
  </tr>
  <tr>
    <th>フォロワー</th>
    <th><%= link_to user.followers.count, user_followers_path(user) %></th>
  </tr>
</table>

<div class='row'>
  <% if user != current_user %>
    <% if current_user.following?(user) %>
      <%= link_to "フォロー外す", user_relationships_path(user.id), class: "btn btn-sm btn-info", method: :delete %>
    <% else %>
      <%= link_to "フォローする", user_relationships_path(user.id), class: "btn btn-sm btn-success", method: :post %>
    <% end %>
  <% end %>
  <%= link_to edit_user_path(user), class: "btn btn-outline-secondary btn-block edit_user_#{user.id}" do %>
    <i class="fas fa-user-cog"></i>
  <% end %>

</div>

ログインしているユーザ以外の住所などが見れないように設定しています。

<div class='container'>
  <div class='row'>
    <div class="col-sm-12 col-md-8 col-lg-5 px-5 px-sm-0 mx-auto">
    <h2>User info</h2>
    <%= form_with model:@user, local:true do |f| %>
      <%= render 'layouts/errors', obj: @user %>
      <div class="form-group">
        <%= f.label :name %>
        <%= f.text_field :name, class: "form-control name" %>
      </div>
     <div class="form-group">
        <%= f.label :image %>
        <%= f.file_field :profile_image, class: "form-control-file user_image", accept: 'image/*' %>
      </div>
      <div class="form-group">
        <%= f.label :introduction %>
        <%= f.text_area :introduction, class: "form-control introduction" %>
      </div>
      <div class="field">
        <%= f.label :email %><br />
        <%= f.email_field :email, autofocus: true, class: "email" %>
      </div>
      <div class="field">
        <%= f.label :postcode, '郵便番号' %>
        <%= f.text_field :postcode, autocomplete: 'postcode', class: 'form-control' %>
      </div>
      <div class="field">
        <%= f.label :prefecture_name, '都道府県' %>
        <%= f.collection_select :prefecture_code, JpPrefecture::Prefecture.all, :code, :name, { include_blank: '選択してください', selected: current_user.prefecture_code}, class: 'form-control' %>
      </div>
      <div class="field">
        <%= f.label :address_city, '市区町村' %>
        <%= f.text_field :address_city, autocomplete: 'address_city', class: 'form-control' %>
      </div>
      <div class="field">
        <%= f.label :address_street, '番地' %>
        <%= f.text_field :address_street, autocomplete: 'address_street', class: 'form-control' %>
      </div>
      <div class="field">
        <%= f.label :address_building, '建物' %>
        <%= f.text_field :address_building, autocomplete: 'address_building', class: 'form-control' %>
      </div>
      <div class="form-group">
        <%= f.submit class: 'btn btn-secondary' %>
      </div>
    <% end %>
  </div>
</div>

おわり

今回は少し難しい内容でしたね。私はjpostalを導入するところで2時間ぐらい悩みました(笑)application.jsファイルに書いてある#の部分はモデル名_カラム名にしないと動かないという初歩的なミスをしてしまっていたので、お恥ずかしい限りです。何はともあれ無事に完成させることができました!次はこの住所からgooglemapのapiを使用して、自分の住所にピンを刺す機能を実装しようと思っています。では今回はこの辺で!最後まで読んでいただき、ありがとうございました!また別の記事でお会いしましょう!

カテゴリー

naska