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

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

ただいまの
回答率

90.52%

  • Ruby on Rails

    7242questions

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

imageとuser_idが入らない

受付中

回答 1

投稿 編集

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

Manamin

score 4

Twitterログインからidを取得し、フォームからuserと一対多のpostを投稿したいのですが、createアクションにて取得できません。

createアクションのsave前でbinding.pryを行うと、以下のようにimageとuser_idが取得できていません。controllerのactionの書き方が間違っているのでしょうか?

[1] pry(#<PostsController>)> @post
=> #<Post:0x007f903269a6a8 id: nil, name: "a", body: "a", tec: "a", point: "a", link: "a", created_at: nil, updated_at: nil, image: nil, user_id: nil>

なおbelongs_to :userにoptional: trueをつける前はUser not existとエラーが出ていました。

主に使っているgemが以下です

# Image Uploader
gem 'carrierwave'
gem 'rmagick', require: 'RMagick'

gem 'omniauth'
gem 'omniauth-twitter'


コードは以下です。
indexはすべてのPostを表示させたいです。

class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :destroy]

  # GET /posts
  # GET /posts.json
  def index
    @posts = Post.all
  end

  # GET /posts/1
  # GET /posts/1.json
  def show
  end

  # GET /posts/new
  def new
    @post = Post.new
  end

  # GET /posts/1/edit
  def edit
  end

  # POST /posts
  # POST /posts.json
  def create
    @post = Post.new(post_params)
    binding.pry

    respond_to do |format|
      if @post.save
        format.html { redirect_to @post, notice: 'Post was successfully created.' }
        format.json { render :show, status: :created, location: @post }
      else
        format.html { render :new }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /posts/1
  # PATCH/PUT /posts/1.json
  def update
    respond_to do |format|
      if @post.update(post_params)
        format.html { redirect_to @post, notice: 'Post was successfully updated.' }
        format.json { render :show, status: :ok, location: @post }
      else
        format.html { render :edit }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /posts/1
  # DELETE /posts/1.json
  def destroy
    @post.destroy
    respond_to do |format|
      format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_post
      @post = Post.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def post_params
      params.require(:post).permit(:name, :user_id, :image, :body, :tec, :point, :link)
    end
end
class SessionsController < ApplicationController
  def create
    user = User.find_or_create_from_auth_hash(request.env['omniauth.auth'])
# request.env['omniauth.auth']に、OmniAuthによってHashのようにユーザーのデータが格納されている。
    session[:user_id] = user.id
    redirect_to root_path, notice: 'ログインしました'
  end

  def destroy
    session[:user_id] = nil
    redirect_to root_path
  end
end
<%= form_with(model: 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">
    <table>
            <tbody>
                <%= form_for @post do |f| %>
                    <div class="field">
                        <tr>
                            <th><%= f.label :TOP画像, class:"image_label" %></th>
                            <td><%= f.file_field :image, class:"image" %></td>
                        </tr>    
                    </div>

                <tr>
                    <div class="field">
                        <th><%= f.label :サービス名 %></th>
                        <td><%= f.text_field :name, id: :post_name %></td>
                    </div>
                </tr>

                <tr>
                    <div class="field">
                        <th><%= f.label :どんなサービス? %></th>
                        <td><%= f.text_area :body, id: :post_body %></td>
                    </div>
                </tr>

                <tr>
                    <div class="field">
                        <th><%= f.label :どんな技術が使われている? %></th>
                        <td><%= f.text_area :tec, size: "20×10", id: :post_tec %></td>
                    </div>
                </tr>

                <tr>
                    <div class="field">
                        <th><%= f.label :どこがオススメ? %></th>
                        <td><%= f.text_area :point, id: :post_point %></td>
                    </div>
                </tr>

                <tr>
                    <div class="field">
                        <th><%= f.label :LINK %></th>
                        <td><%= f.text_area :link, id: :post_link %></td>
                    </div>
                </tr>    

                <tr>
                    <div class="actions">
                        <th></th>
                        <% f.hidden_field :user_id, value: @user.id %>
                        <td><%= form.submit %></td>
                    </div>
                </tr>
            <% end %>
        </tbody>
    </table>                
<% end %>
class User < ApplicationRecord
  has_many :posts

  #引数に関連するユーザーが存在すればそれを返し、存在しまければ新規に作成する
  def self.find_or_create_from_auth_hash(auth_hash)
#OmniAuthで取得した各データを代入していく
    provider = auth_hash[:provider]
    uid = auth_hash[:id]
    nickname = auth_hash[:info][:nickname]
    image_url = auth_hash[:info][:image].to_s.sub('normal', 'bigger')

    User.find_or_create_by(provider: provider, id: uid) do |user|
      user.nickname = nickname
      user.image_url = image_url
    end
  end
end
class Post < ApplicationRecord
  mount_uploader :image, ImageUploader
  belongs_to :user, optional: true
end
ActiveRecord::Schema.define(version: 20180701050628) do

  create_table "posts", force: :cascade do |t|
    t.string "name"
    t.text "body"
    t.text "tec"
    t.text "point"
    t.text "link"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.text "image"
    t.integer "user_id"
  end

  create_table "users", force: :cascade do |t|
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "provider"
    t.string "nickname"
    t.string "image_url"
  end

end
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :check_login



  private
    def check_login
      if session[:user_id]
        @user = User.find_by(id: session[:user_id])
      end
    end
end
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

0

imageが何を取得するのかわかりませんが、user_id
UserモデルとPostモデルが正しく紐づいているのであれば
user.posts.create()でUserに紐づいたPostを作成することで取得できるはずです。

現在のコードは正直慣習的に好ましくないですが、その書き方を貫くのであれば
newアクションで@userを定義してやればuser_idに関してはうまくいくと思います。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/07/10 15:47 編集

    ありがとうございます!imageはフォームから投稿した画像で、Userと紐づける前は正常に投稿できていました。慣習的に好ましい書き方についてももしよければ教えていただきたいです。(なんども書かないようにbefore_actionに指定するなどでしょうか?)

    キャンセル

  • 2018/07/10 22:13

    imageはすみません、よくわかりません。強いて気になるところを挙げるとするならデータ型がtextになってるくらいですが、以前正常に取得できていたのなら別の原因なのでしょう。
    慣習的に好ましいというのは、上でuser.posts.create()と書いたように
    例えばここでの@post = Post.newを@post = current_user.posts.buildにしたりすることです。
    こう書くことでcurrent_userに紐づいたpostを作ることができますが
    個人の自由なので好きに書くといいと思います。

    キャンセル

  • 2018/07/12 10:09 編集

    createアクションに@post.user_id = @current_user.idと記述したところuser_id取れました!ありがとうございました!

    キャンセル

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

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

関連した質問

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

  • Ruby on Rails

    7242questions

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