質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.05%

Railsのバリデーションに関する質問です!

受付中

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 169

sn.jr

score 53

質問

現在、投稿(Postモデル)のジャンル(Genreモデル, nameカラム)分けを行いたく、中間モデルManageを用いて作成しています。 schema.rbは下に明記しています! 
そこでGenreモデルのバリデーションに関する質問なのですが、Genreモデルにはnameというカラムがありそこにジャンル名を入れるのですが、今の仕様だと空欄(nil)もジャンル名として保存されてしまいます。今まではそこでvalidates :name, presence: trueにして対応してきましたが、「ジャンル名は空欄でも良い」仕様にしたいです。
整理すると
Genreモデルのnameに空欄は保存させたくないが、nameが空欄でもフォームは送信できるようにしたい。
nilというデータでの保存を防ぎたい

少し説明が難しく、わかりづらい文章になってしまっているので質問などしていただけると幸いです!

class Genre < ApplicationRecord
  has_many :manages
  has_many :posts, through: :manages
  validates :name, uniqueness: true
ActiveRecord::Schema.define(version: 2019_12_28_045120) do

  create_table "genres", force: :cascade do |t|
    t.string "name"
    t.integer "status"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

  create_table "manages", force: :cascade do |t|
    t.integer "genre_id"
    t.integer "post_id"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["genre_id"], name: "index_manages_on_genre_id"
    t.index ["post_id"], name: "index_manages_on_post_id"
  end

  create_table "posts", force: :cascade do |t|
    t.string "title"
    t.text "body"
    t.datetime "posted_at"
    t.text "reason"
    t.integer "rank"
    t.string "summary"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.integer "status"
    t.string "url"
  end

  create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

end

投稿とジャンルを保存するフォーム

<div class="container">
<%= form_with(model: [:mypage, post], local: true) do |form| %>
  <% if post.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>

      <ul>
        <% post.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>
  <div class="form-group">
    <%= form.text_field :title, class:"form-control", placeholder:"タイトル" %>
  </div >
  <div class="form-group">
    <%= form.text_area :body, class:"form-control", placeholder:"自分の辞書をマークダウン記法で記入してみよう" %>
  </div>

  <div class="field">
    <%= form.label :status %>
    <%= form.select :status, Post.statuses.keys,class:"form-control" %>
  </div>

  <div class="field">
    <%= form.label :posted_at %>
    <%= form.datetime_select :posted_at %>
  </div>

  <div class="form-group">
    <%= form.text_area :reason, class:"form-control", placeholder:"メモした経緯を書いてみよう" %>
  </div>

  <div class="field">
    <%= form.label :rank %>
    <%= form.select :rank, Post.ranks.keys, class:"form-control" %>
  </div>

  <div class="form-group">
    <%= form.label :summary %>
    <%= form.text_field :summary, class:"form-control" %>
  </div>

  <div class="form-group">
    <%= form.label :URL %>
    <%= form.text_field :url, class:"form-control" %>
  </div>

  <%= form.label :genre, 'ジャンル' %>
    <%= form.collection_check_boxes(:genre_ids, Genre.all, :id, :name) do |genre| %>
      <%= genre.label do %>
        <%= genre.check_box %>
        <%= genre.text %>
      <% end %>
    <% end %><br>
    <%= fields_for @genre, :genres do |form| %>
      <%= form.label :新しくジャンルを作る %>
      <%= form.text_field :name, class:"form-control" %>
    <% end %>

  <div class="actions">
    <%= form.submit class:"btn btn-info" %>
  </div>
<% end %>
</div>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

0

今でも、
1)nameが空欄でもformの送信ができる
2)nameがnilでの保存は防ぐ
はできていると思います。
何が足りないのでしょう?
もしかすると
3)nilでの保存は出来ないが空文字列で保存したい
でしょうか
3')nilで送られてきたら空文字列で保存する
でしょうか。
なお、
nameが空欄の場合ブラウザはnameを送りません。ですのでRails側がnameを参照するとnilになります。
nilは送らない、空欄を送る というのは出来ません。
JS使えばできるのかもしれませんが、意味ないのでやったことはないです。

ああ、『空欄は保存したくない」ですね。
すると送られてきたformはどのように処理したいのでしょう???

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/12/29 13:39

    ご回答ありがとうございます!空欄というのはnilのことを示してました。つまりnilでもデータを送ることはできるが、name: nilとして保存させたくないということです。その理由としてnameはuniquenessであるため、nilを一度保存してしまうと、それ以降nilでの保存つまりnameを空欄にして送信することができなくなってしまうからです。

    キャンセル

  • 2019/12/29 16:11

    しかし、空欄(空文字)を入れても uniqunessに引っかかりますよ?

    空欄を許し、かつ空欄以外ではuniquである
    としたい?

    キャンセル

  • 2019/12/30 10:02

    そうなんです。おっしゃる通り、空欄を許し、かつ空欄以外ではuniquを目指してます!

    キャンセル

0

何をしたいのか、が正確に伝わるようにしましょう

validates :name, uniqueness: true, if: :present?

かな

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.05%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る