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

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

ただいまの
回答率

91.05%

  • Ruby

    6142questions

    Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

  • Ruby on Rails

    6014questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Rails 2つのフォームから1つのDBにデータ登録ができない

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 128

ruby_0ct

score 16

ブログ記事の投稿フォームでDBに格納したいと思っています。
DBは「ブログ本体のDB」と「カテゴリー用のDB」の2つがあります。

投稿フォームで、ブログタイトルや本文のフォームとカテゴリーを選択するフォーム、2つのフォームがあり、
カテゴリーフォームは「カテゴリー用のDB」から参照し、 collection_select でプルダウン表示させています。

buildメソッドや accepts_nested_attributes_for などを記述し、2つのフォームの関係性を認識させようとしましたが、

NoMethodError in BlogsController#new
undefined method `blogcategories' for nil:NilClass

@blog.blogcategories.build

とエラー表示され、うまくできません。

様々なサイトを見て同じように buildメソッド を書いたのですがなぜこうなるのかよくわからずいまいちピンとこないので、ご指摘いただければ助かります。

また、DBの関係は1つの記事につき、1つのカテゴリーしか参照できませんが、カテゴリーからはいくつもの記事に参照できる「1対多」の関係です。

blogs_controller.rb

createアクションは手をつけていません。

def new
    @blog.blogcategories.build

    @dbsort = Blogcategory.new # カテゴリーの表示
end


def create
    @blog = Blog.new(blog_params)

    respond_to do |format|
      if @blog.save
        format.html { render :index }
        format.json { render :show, status: :created, location: @blog }
      else
        format.html { render :new }
        format.json { render json: @blog.errors, status: :unprocessable_entity }
      end
    end
end


private
    def blog_params
      params.require(:blog).permit(:blogtitle, :blogcategory_id, :content, blogs_attributes[:blogcategory_id])
    end

/views/blogs/new.html.erb

投稿フォームのview
カテゴリーの部分はプルダウン(select)で表示させています。

<h1>ブログを投稿する</h1>

  <%= form_for(@blog) do |f| %>
      <% if @blogchou.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(@blog.errors.count, "error") %> prohibited this blog from being saved:</h2>

          <ul>
          <% @blog.errors.full_messages.each do |message| %>
            <li><%= message %></li>
          <% end %>
          </ul>
        </div>
      <% end %>

      <%= f.text_field :blogtitle, placeholder: 'ブログタイトル' %>

      <%= form_for @dbsort do |c| %>
        <%= c.collection_select :id, Blogcategory.all, :id, :category %>
      <% end %>

      <%= f.text_field :content, placeholder: 'ブログの内容' %>

      <%= f.submit 'ブログを投稿する' %></div>
    <% end %>

/models/blogcategory.rb

カテゴリー用DBのモデル

class Blogcategory < ApplicationRecord
  has_many :blogs
  accepts_nested_attributes_for :blogs, allow_destroy: true 
end

/models/blog.rb

ブログ本体DBのモデル

class Blog < ApplicationRecord
  belongs_to :blogcategory
end
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+2

エラーメッセージの

undefined method `blogcategories' for nil:NilClass

は,NilClass クラスのインスタンスである nil に blogcategories というメソッドは定義されていない,ということです。

とすれば,@blog が nil であると分かります。

BlogsController の new メソッドを見ると,いきなり

    @blog.blogcategories.build

で始まっていますね。

before_action などで @blog をセットしているのでなければ,ここで初めて @blog が出てくるのですが,「未定義のインスタンス変数の値は nil」というルールがあるので,nil の blogcategories メソッドを呼び出そうとしていることになるのです。

(追記)

エラーの原因は以上ですが,new メソッドで最初にやるべきことはおそらく 

@blog = Blog.new

で空の(フォーム用の)Blog オブジェクトを作ることでしょうね。

で,Blog モデルの定義を見ると

belongs_to :blogcategory

なので,そもそも Blog に blogcategories というメソッドはありません。(複数あるはずがありませんよね)
belong_to の解説(参考にしたもの)をもう一度よく読んでみてください。
今の場合,blogcategory という単数形のメソッドが使えます。

ただ,new メソッドで @blog.blogcategory.build ってやる必要がよくわかりません。

また,フォームが入れ子になっているのもよく分かりません。
Blog のためのフォームなので,カテゴリーを選ぶところは category_id の値を select させればよいと思うのですが。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/12/28 02:47

    @blog.build_blogcategory とすることで無事表示されました。

    実はsubmitしても無反応だったためbuildあたりが怪しいからではないかと推測し、この質問をしたのですが、buildしても相変わらず無反応なため、buildではなくform_forの入れ子の部分とルーティングの仕方が原因ではないかとわかりました。

    また改めて調べて実際にやってみたいと思います。
    丁寧にご指摘いただきbuildについて大変参考になりました。ありがとうございました。

    キャンセル

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

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

関連した質問

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

  • Ruby

    6142questions

    Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

  • Ruby on Rails

    6014questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。