前提・実現したいこと
Railsで簡単なイベント閲覧アプリを作成しています。
イベントを登録する際にバリデーションをかけて、以下のエラーが発生したので解決したいのですが、できません。
発生している問題・エラーメッセージ
イベントを登録する際に、以下のバリデーションをかけています。
・イベント名(event_name)が存在すること
・開催地の郵便番号(postcode)が北海道であること
・開催地の住所が存在すること
・登録するイベントの開始日が今日以降であること
・登録するイベントの終了日が開始日以降であること
問題は、
・イベント名(event_name)が存在すること
というバリデーションは有効であるのに対して
・開催地の住所が存在すること
というバリデーションは無効であることです。
undefined method `[]' for nil:NilClass
このエラーメッセージは開催地の住所が空であるにも関わらず、緯度経度を取得しようとしているがゆえに起きるメッセージです。
「開催地の住所が存在すること」というバリデーションが無効という判断は、上記エラーより推測しました。
該当のソースコード
以下はモデル(event.rb)のコードです。
ruby
1class Event < ApplicationRecord 2 has_many :interests 3 has_many :interested_users, through: :interests, source: :user 4 has_many :likes 5 has_many :liked_users, through: :likes, source: :user 6 belongs_to :category 7 8 with_options presence: true do 9 validates :event_name 10 validates :place 11 end 12 validates :postcode, format: {with: /\A[0-9]{5,6}\z/} 13 validates :postcode, format: {without: /\A[1-3][0-9]{5}\z/} 14 validate :not_before_today 15 validate :not_before_start_on 16 after_validation :geocode 17 18 def not_before_today 19 errors.add(:start_on, 'Please set today or after today') if start_on.nil? || start_on < Date.today 20 end 21 22 def not_before_start_on 23 errors.add(:end_on, 'Please set after start day') if end_on.nil? || end_on < start_on 24 end 25 26 # ↓↓住所から緯度経度を取得してDBに保存するための記述↓↓ 27 private 28 def geocode 29 address = (place + place_building) 30 uri = URI.escape("https://maps.googleapis.com/maps/api/geocode/json?address="+address.gsub(" ", "")+"&key=AIzaSyCuZz7CQo9VlX7NCAFAPiNevqd7NTWpXO8") 31 res = HTTP.get(uri).to_s 32 response = JSON.parse(res) 33 self.latitude = response["results"][0]["geometry"]["location"]["lat"] 34 self.longitude = response["results"][0]["geometry"]["location"]["lng"] 35 end 36 37end
関連するコントローラ(events_controller.rb)は以下のコードです。
ruby
1class EventsController < ApplicationController 2 before_action :authenticate_user!, only: [:show, :new, :create] 3 4 def index 5 @search = Event.ransack(params[:q]) #ransackメソッド推奨 6 @events = @search.result.includes(:category).order(:start_on) 7 @allevents = Event.where('start_on >= ?', Date.today).order(:start_on) 8 end 9 10 def new 11 @event = Event.new 12 end 13 14 def create 15 @event = Event.new(event_params) 16 17 if @event.save 18 redirect_to action: 'index' 19 else 20 render "new" 21 end 22 23 end 24 25 def show 26 @event = Event.find(params[:id]) 27 @interest = Interest.new 28 @like = Like.new 29 end 30 31 private 32 def event_params 33 params.require(:event).permit(:event_name, :url, :start_on, :end_on, :category_id, :postcode, :place, :place_building, :latitude, :longitude) 34 end 35end 36
投稿フォームのビュー(new.html.erb)は以下の通りです
ruby
1<div class="main-wrapper"> 2 3 <h3>イベント登録する</h3> 4 5 <div class="form-wrapper"> 6 7 <%= form_for @event do |f| %> 8 9 <%= render 'layouts/error_messages', model: f.object %> 10 11 <div class="event_name"> 12 <%= f.label :event_name, "イベント名 (必須)" %> 13 <%= f.text_field :event_name %> 14 </div> 15 16 <div class="postcode"> 17 <%= f.label :postcode, "郵便番号 (必須)" %> 18 <%= f.text_field :postcode, size: "10", maxlength: "8", onKeyUp: "AjaxZip3.zip2addr(this,'','addr11','addr11');", placeholder: "ハイフンなし7桁" %> <%# name属性のzip11は無くてもいい %> 19 </div> 20 21 <div class="place"> 22 <div class="place__address"> 23 <%= f.label :place, "住所" %> 24 <%= f.text_field :place, name: "addr11", size: "60", class: "false-place", placeholder: "郵便番号から自動入力されます" %> 25 </div> 26 <div class="place__building"> 27 <%= f.label :place_building, "建物名等" %> 28 <%= f.text_field :place_building, placeholder: "あったら助かります" %> 29 </div> 30 </div> 31 32 <div class="url"> 33 <%= f.label :url, "イベントURL" %> 34 <%= f.text_field :url, class:'form-control', placeholder: "例: https://hokkaido.com" %> 35 </div> 36 37 <div class="start_on"> 38 <div class="start_on__label"> 39 <%= f.label :start_on, "開始日" %> 40 </div> 41 <%= f.date_field :start_on, value: Time.now.strftime("%Y-%m-%d"), class: 'form-control' %> 42 </div> 43 44 <div class="end_on"> 45 <div class="end_on__label"> 46 <%= f.label :end_on, "終了日" %> 47 </div> 48 <%= f.date_field :end_on, value: Time.now.strftime("%Y-%m-%d"), class: 'form-control' %> 49 </div> 50 51 <div class="category clearfix"> 52 <div class="category__label"> 53 <%= f.label :category_id, "カテゴリー"%> 54 </div> 55 <%= f.select :category_id, [["グルメ",1], ["お祭り",2], ["花火",3], ["よさこい",4], ["その他",5]] %> 56 </div> 57 58 <%= f.submit '登録', class:'btn btn-primary add-btn' %> 59 60 <% end %> 61 62 </div> 63 64</div>
投稿フォームのビューにかけているjs(new.js)は以下の通りです
js
1$(function(){ 2 $('.false-place').keyup(function(){ 3 $('input[name="addr11"]').attr('name', 'event[place]'); 4 }); 5});
試したこと
①バリデーションの順番を変えましたが、効果はありませんでした。
「イベント名(event_name)が存在すること」はバリデーションが効いて「イベント名を入力してください」というエラーメッセージが表示されます。
②mysqlのplaceカラムのヌル許可にチェックを入れデフォルトを「NULL」にしましたが、効果はありませんでした。
画像はテーブルの構造です。
補足情報(FW/ツールのバージョンなど)
プログラミングを始めて1ヶ月半です。初めての質問でわかりづらい部分もあると思いますが、ご回答いただけると幸いです。
Rails 5.2.3
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/11/02 03:13
2019/11/02 05:12
2019/11/02 08:23 編集
2019/11/02 08:34
2019/11/02 08:53
2019/11/02 09:33
2019/11/02 09:44
2019/11/02 09:53
2019/11/02 12:22 編集
2019/11/02 12:36
2019/11/02 12:42