3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Ruby on Rails]データ登録時に重複したレコードがあった場合、登録させない

Last updated at Posted at 2020-09-27

#背景
オリジナルアプリをデプロイ後、重複したデータを登録されていることに気づきます。
スクリーンショット 0002-09-27 午前9.43.35.png

アプリの仕様としては、登録するレコードは重複させたくないのです。

データベースを確認すると、
登録するユーザが異なっていれば、登録できてしまうことが判明。
スクリーンショット 0002-09-27 午前9.44.59.png

解決にそこそこ時間がかかったので、備忘として記録します。
#問題箇所
controllerにデータ登録時の条件を設けていました。

require 'rubygems'
require 'mechanize'

def create
    f = (params[:wiki_url])
    
    unless 
      f.start_with?("https://ja.wikipedia.org/wiki/")
      flash[:notice] = "無効なURLが入力されたため保存できませんでした。"
      redirect_to action: 'new'
      return
    else
      agent = Mechanize.new
      page = agent.get(f) 
      page.encoding='utf-8'

以下、省略...

unless文には、入力したデータ(URL)に「https://ja.wikipedia.org/wiki/」
が含まれていない場合は、登録させないという条件を組んでいました。

しかし、重複したレコードがある場合、登録させないという条件が含まれていなかったため、
写真のような同じデータが登録されてしまったわけです。
#解決(結論)
以下のように書き換えて、解決しました。

require 'rubygems'
require 'mechanize'

  def create
    f = (params[:wiki_url])

    if not 
      f.start_with?("https://ja.wikipedia.org/wiki/")
      flash[:notice] = "無効なURLが入力されたため登録できませんでした。"
      redirect_to action: 'new'
      return
    elsif
      Company.where(page_url: "#{f}").count >= 1
      flash[:notice] = "登録済みのURLが入力されたため登録できませんでした。"
      redirect_to actiont: 'new'
      return
    else
      agent = Mechanize.new
      page = agent.get(f) 
      page.encoding = 'utf-8'

以下、省略...

teratailの記事が参考になり、解決に至りました。
:point_right:同じ名前のデータが2件以上登録されているレコードをActiveRecordを用いて取得したいです。

変更点は大きく2つです。

  • unless文からif not文に変更
  • whereメソッド追加(ココがポイント!)

##unless文からif not文に変更
ruby unless文にelsifはないよ。。。
だそうです。

不正データの入力防止の条件に加えて、重複防止の条件を追加したい。
しかし、unless文にelsifが使えないので、
if not文に変えてelsifを追加しました。

##whereメソッド追加(ココがポイント!)
条件(処理)の流れは以下の通りです。

  • whereメソッドで、テーブル内の条件に一致したレコードの数を取得する
  • 取得したデータの数を条件にかけて1以上(データがあるか)判定する
  • 1以上(データがあり)ならば、受付けない

###whereメソッドで、テーブル内の条件に一致したレコードの数を取得する

.where("条件")で条件にあうレコードを取得できます。

モデル名.where("条件")

.
今回、取得するのは Companyモデル の page_urlカラムです。

Company.where(page_url)

.
さらに、page_urlカラム内に入力したデータと一致するものを検索にかけたいので、
下記のように付け加えます。

Company.where(page_url: "#{f}")

.
 #{f}は変数内の文字列を表しています。
変数fは以下の場所で定義しており、中身はこのようになっています。

require 'rubygems'
require 'mechanize'

  def create
    f = (params[:wiki_url]) <= ココです。

以下、省略...

image.png

.
page_urlカラム内で検索をかけた結果、いくつあったか判定するために
countメソッドを追加します。

Company.where(page_url: "#{f}").count

###取得したデータの数を条件にかけて1以上(データがあるか)判定する

1以上、つまり入力したデータと同じURLの数を数えて1以上あるか確認します。

Company.where(page_url: "#{f}").count >= 1

###1以上(データがあり)ならば、受付けない
image.png

#おまけ

アプリに反映させているので、是非遊んでみてください。
Unsung:hero
image.png

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?