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

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

ただいまの
回答率

88.23%

railsでユーザー情報が登録されません。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 958
退会済みユーザー

退会済みユーザー

railsでユーザー情報の登録機能を作成しています。
入力画面(index)、確認画面(confirm)、登録完了画面(complete)とページ遷移を行います。
確認画面にデータを表示させるところまでは作成できたのですが、
確認画面で登録ボタンを押すと、id・作成日時・更新日時のみが登録され、
ユーザ名、Email、パスワードなどがDB上に反映されません。
sqlite3で検索をかけてみると「ID||||||作成日時|更新日時」のように表示されます。

class SignupController < ApplicationController
  layout 'info_get'
  protect_from_forgery

  include SessionManagement
  before_action :is_session, only: [:index, :confirm]
  before_action :sign_in!, only: [:complete]

  def index
    @title = 'ユーザー情報入力'
    @errMsg = Hash.new

    dalli = Dalli::Client.new('localhost:11211')

    if request.get? then 
      @user = User.new
      if dalli.get('signup_user') != nil then
        signup_user = dalli.get('signup_user')
        @user.name = signup_user.name
        @user.email = signup_user.email
      end
    else
      @user = User.new user_params

      if @user.valid? then
        dalli.set('signup_user', @user)
        redirect_to '/signup/confirm'
      else
        #エラーメッセージの連想配列を生成
        @user.errors.messages.each do |key, val|
           if key == :password_confirmation && !@errMsg.has_key?(:password) then
             @errMsg[:password] = val[0]
             next
           end
          @errMsg[key] = val[0]
        end
      end
    end
  end

  def confirm
    @title = 'ユーザー情報入力確認'
    dalli = Dalli::Client.new('localhost:11211')

    if request.post? then
      @user = User.new user_params
      if @user.save(validate: false) then
        login_user = User.find_by(email: @user.email)

        if login_user && login_user.authenticate(@user.password) then
          dalli.delete('signup_user')
          reset_session
          dalli.set('login_user', login_user)
          redirect_to '/signup/complete'
        end
      else 

      end
      redirect_to '/signup/confirm'
    else
      @user = dalli.get('signup_user') 
    end
  end

  def complete
    @title = 'ユーザー情報登録完了'
  end

  private
  def user_params
    params.require(:user).permit(:name, :email, :password, :password_confirmation)
  end

end


確認画面でフォームを実装しているコードは下記になります。

<%= form_for(@user, url:{controller: 'signup', action: 'confirm'}) do |f| %>
  <%= f.hidden_field :name %>
  <%= f.hidden_field :email %>
  <%= f.hidden_field :password %>
  <%= f.hidden_field :password_confirmation %>
  <input type="button" value="戻る"  onClick="location.href='/signup'">
  <%= f.submit '登録' %>
<% end %>

DBテーブルのスキーマは下記の通りです。

create_table "users", force: :cascade do |t|
    t.text "name"
    t.text "email"
    t.text "password_digest"
    t.text "kari_password"
    t.text "kari_created_at"
    t.text "session_id"
    t.text "lastlogin_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

前提として、scaffoldを使用していません。
また、セッション管理の為にmemchachedを使用しています。

どのように対処したらよいのでしょうか。


2017/7/25追記
下記の修正を施しました。

■修正後のコントローラー

class SignupController < ApplicationController
  layout 'info_get'
  protect_from_forgery

  include SessionManagement
  before_action :is_session, only: [:index, :confirm]
  before_action :sign_in!, only: [:complete]

  def index
    @title = 'ユーザー情報入力'
    @errMsg = Hash.new

    if request.get? then 
      @user = User.new
      if Rails.cache.exist?('signup_user') then
        signup_user = Rails.cache.read('signup_user')

        @user.name = signup_user.name
        @user.email = signup_user.email
      end
    else
      @user = User.new user_params

      if @user.valid? then
        Rails.cache.write('signup_user', @user)
        redirect_to '/signup/confirm'
      else
        #エラーメッセージの連想配列を生成
        @user.errors.messages.each do |key, val|
           if key == :password_confirmation && !@errMsg.has_key?(:password) then
             @errMsg[:password] = val[0]
             next
           end
          @errMsg[key] = val[0]
        end
      end
    end
  end

  def confirm
    @title = 'ユーザー情報入力確認'

    if request.post? then
      @user = Rails.cache.read('signup_user')
      if @user.save(validate: false) then
        login_user = User.find_by(email: @user.email)

        if login_user && login_user.authenticate(@user.password) then
          Rails.cache.delete('signup_user')
          Rails.cache.write('login_user', login_user)
          redirect_to '/signup/complete'
        end

      end
      redirect_to '/signup/confirm'
    else
      @user = Rails.cache.read('signup_user')
    end
  end

  def complete
    @title = 'ユーザー情報登録完了'
  end

  private
  def user_params
    params.require(:user).permit(:name, :email, :password, :password_confirmation)
  end

end

■userモデル

class User < ApplicationRecord
  include ActiveModel::Model

  has_secure_password validations: false

  attr_accessor :name, :email, :password, :password_confirmation

  validates :name, presence: {message: 'ユーザー名を入力して下さい。'}
  validates :email, presence: {message: 'Emailを入力して下さい。'}
  validates :password, presence: {message: 'パスワードを入力して下さい。'}
end
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

dalli = Dalli::Client.new('localhost:11211')
をコントローラーごとにやって、
dalliを初期化してしまっているからいけないのでは?
じゃあどうやって共通化するねんって話になりますが、
Railsはwebアプリなのでmethodごとに違うインスタンスをとる
createする時のcontrollerとindexする時のcontrollerは別インスタンスなので
色々試行錯誤するよりは

参考サイトの後半にあるように
config.cache_store = :dalli_store
として
Rails.cache.write 'signup_user',...
user = Rails.cache.read 'signup_user'
でmethodを跨いでデータを共有する方がいいと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/07/26 00:03

    なぜかコマンドプロンプトには下記のSQLが出力されていました。
    insert into users (created_at, updated_at) values (?, ?)
    モデルを作成した時に自動的にnameなどのカラムも登録対象になると思っていたんですが、
    必ずしもその通りにsqlを作成してくれるわけではないのでしょうか。

    ちなみに、sqlite3を使用しています。
    なのでカラム型はtextにしています。

    キャンセル

  • 2017/07/26 00:16

    うーむ、謎ですね、バリデーションをコメントアウトするのも、やってみて下さい。
    あと、userのインスタンスではなく、パラメータをchache してみるのはどうでしょう?

    キャンセル

  • 2017/07/26 01:22

    とりあえずなんとか解決できました。
    明確にこれが原因とは言い切れませんが、モデル作成の過程でミスがあったのでは考えています。
    (パスワードを暗号化する対応に誤りがあった)

    今回の対処方法は下記の通りです。

    1.userモデルを削除
    2.項目を見直した上でモデルをgenerate
      (passwordとしていた箇所をpassword_digestに変更)
    3.rails db:migrate
      (参考:http://qiita.com/chobi9999/items/20b962a324a0bdbfc0dc
    4.モデルファイルのuser.rbに、以前のuser.rbの記述を一部削除した上で処理を追加
      ※削除した内容
       include ActiveModel::Model
       attr_accessor :name, :email, :password, :password_confirmation
    5.登録処理を実行

    これで次のステップに進められます。
    ありがとうございました。




    キャンセル

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

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

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