0

Ruby 2 を使用して、Rails 4 で自分の Rails アプリケーションの 1 つを書き直しています。元のアプリケーションは、Michael Hartl の Ruby on Rails Tutorial の 3.2 バージョンを使用していました。アプリケーションの 3.2 バージョンを新しい Rails 4 バージョンにコピーしています。current_user が正しく設定されていないようです。current_user を使用するすべてのルートは、レコードが適切にアクセスされ、ユーザーがログインし、ロケールが設定されている場合でも、ID とロケールが欠落して中止されます。current_user を使用したルートを含まないランディング ページで、ロケールを変更し、選択したロケールの正しいテキストと画像を表示できます。残念ながら、メイン サイトのヘッダー パーシャルには edit_user_path(current_user) 参照が含まれています。これは、ランディング ページと、ユーザーに関係のない Web サイトの別のセクションを除いて、自分の Web サイトにページを表示できないことを意味します。

show アクションを表示しようとしている場合の例を次に示します。current_user を参照するルートにアクセスしようとすると、常に同様のエラーが発生します。

No route matches {:controller=>"users", :action=>"show", :locale=>#<User id: 3, first_name: "first_name", last_name: "last_name", username: "username", email: "myemail@company.com", password_digest: "$2a$10$y73jlk0hQYKLClmXQI5iHe/fqXO66hJD3muWjDg5ziCD...", city: "MyCity", state_id: 3521, country_id: 233, remember_token: "8cce0e523a879e179dd5b23df04acc8d1cf3108e", password_reset_token: "nU1FbWD2nuXx23jnOmOkAQ", password_reset_sent_at: "2013-10-20 22:36:44", bio: "Here is my bio info...", active_user: "3", age_group: "3", gender: "F", admin: true, visible: true, created_at: "2012-08-28 19:43:27", updated_at: "2013-10-21 22:36:43", state_province: "MyState", broadcaster: true, language_id: 1, admin_localize: false, sos_student: false, send_newsletter: false, special_newsletter: true, temp_broadcaster: false, media_creator_id: 46, bad_email: false, banned: false, notify_resp_me: true, saved_micropost_id: 1, saved_topic_id: 56, saved_discussion_id: 1, notify_reply_me: true, on_profile_page: false, notify_new_disc: true>, :id=>nil, :format=>nil} missing required keys: [:locale, :id]  

current_user は nil のようです。私のremember_tokenロジックが原因である可能性があります。過去数時間、sessions_helper.rb を見てきましたが、何が間違っていたのかわかりません。

これが私の sessions_helper.rb コードです。注: 私の login(user) メソッドでは、Cookie を永続的に保存するか、セッションで使用するかをユーザーが決定できるようにしています。このチュートリアルでは、Cookie を削除するにはログアウトする必要がある永続的な Cookie を作成します。

  def current_user
    remember_token = User.encrypt(cookies[:remember_token])
    @current_user ||= User.find_by(remember_token: remember_token)
  end

  def current_user?(user)
    user == current_user
  end

  def login(user)
    remember_token = User.new_token
    if params[:remember_me]
      cookies.permanent[:remember_token] = remember_token
    else  
      cookies[:remember_token] = remember_token
    end  
    user.update_attribute(:remember_token, User.encrypt(remember_token))
    self.current_user = user
  end

  def logged_in?
    !current_user.nil?
  end

  def logged_in_user
    unless logged_in?
      store_location
      redirect_to login_path, notice: "#{t :must_login}"
    end
  end

  def logout
    self.current_user = nil
    cookies.delete(:remember_token)
    flash[:success] = "#{t :logout}"
  end

  def current_user=(user)
    @current_user = user
  end

  def redirect_back_or(default)
    redirect_to(session[:return_to] || default)
    session.delete(:return_to)
  end

  def store_location
    session[:return_to] = request.url if request.get?
  end

これが私の sessions_controller.rb ロジックです。注: メール アドレスまたはユーザー名を使用してログインできるようにします。ロジックはチュートリアルに基づいています。ただし、@user にリダイレクトする代わりに、別のパスを表示します。その違いによって最終結果が変わることはありません。

  def create
    user = User.find_by_email(params[:session][:email_user])
    if user && user.authenticate(params[:session][:password])
      if user.active_user == "1"
        flash[:error] = "#{t :flash_sessions_error1}"
      else
        flash[:success] = "#{t :flash_sessions_success}"   
        login user
      end  
      redirect_back_or home_path
    else
      user = User.find_by_username(params[:session][:email_user])
      if user && user.authenticate(params[:session][:password])
        if user.active_user == "1"
          flash[:error] = "#{t :flash_sessions_error1}"
        else   
          flash[:success] = "#{t :flash_sessions_success}"
          login user
        end  
        redirect_back_or home_path
      else
        flash.now[:error] = "#{t :flash_sessions_error2}"
        render "new"
      end
    end
  end

これがuser.rbの私のコードです。

  before_create :create_remember_token

  def User.encrypt(token)
    Digest::SHA1.hexdigest(token.to_s)
  end

  def User.new_token
    SecureRandom.urlsafe_base64
  end

  private

    def create_remember_token
      self.remember_token = User.encrypt(User.new_token)
    end

これが users_controller.rb の show アクションです。

  def show
    @user = User.find(params[:id])
    @microposts = @user.microposts.order("created_at DESC").first(20)
    @discussions = @user.discussions.order("created_at DESC").first(20)
  end

これは、ユーザーのすべてのルートに対する私の rake ルート出力です。

following_user GET    /:locale/users/:id/following(.:format)                users#following {:locale=>/en|es|fr|pt/}
followers_user GET    /:locale/users/:id/followers(.:format)                users#followers {:locale=>/en|es|fr|pt/}
         users GET    /:locale/users(.:format)                              users#index {:locale=>/en|es|fr|pt/}
               POST   /:locale/users(.:format)                              users#create {:locale=>/en|es|fr|pt/}
      new_user GET    /:locale/users/new(.:format)                          users#new {:locale=>/en|es|fr|pt/}
     edit_user GET    /:locale/users/:id/edit(.:format)                     users#edit {:locale=>/en|es|fr|pt/}
          user GET    /:locale/users/:id(.:format)                          users#show {:locale=>/en|es|fr|pt/}
               PATCH  /:locale/users/:id(.:format)                          users#update {:locale=>/en|es|fr|pt/}
               PUT    /:locale/users/:id(.:format)                          users#update {:locale=>/en|es|fr|pt/}
               DELETE /:locale/users/:id(.:format)                          users#destroy {:locale=>/en|es|fr|pt/}

私はこれを見続けますが、今のところ、私が間違っていることはわかりません。

どんな助けでも大歓迎です。

4

1 に答える 1

1

今朝、ログをもう一度見てみました。ロジックが正しいレコードを取得していることを再度確認しました。エラーの最後にIDとロケールの両方が欠落していると書かれていたので、 current_user が正しく設定されていないと思いました。正しいレコードがログにあったので、locale: I18n.locale.to_sを次のようにパスの 1 つに追加することにしました。

edit_user_path(current_user, locale: I18n.locale.to_s)

ルートによってロケールを追加した後、ロジックは機能しました。もう 1 つの問題は、Rails 3 では機能していたが Rails 4 では機能しない default_url_options のデフォルトに関連していました。

Rails.application.routes.default_url_options[:locale]= I18n.locale 

I18n コードは、Rails 3 でコーディングしたとおりに機能しました。locale 句を追加しなかったリンクでも機能することがわかりました。これが他の人に役立つことを願っています。

于 2013-10-22T15:29:11.940 に答える