Rails 6.0.0 TypeError求助:POST API调用时nil转字符串失败
Fixing the 500 Error & TypeError in Your Cross-App API Authentication
Let's break down what's causing this 500 error and the TypeError - no implicit conversion of nil into String, then fix it step by step:
Key Issues Identified
- Mismatched Parameter Names: Your homework app sends data under the
api_userkey, but Devise (assuming you're using it for main app auth) expects parameters under your resource name (typicallyuserfor aUsermodel). This confuses Warden's authentication logic. - Incorrect Request Format: jQuery's
$.postdefaults to sendingapplication/x-www-form-urlencodeddata, not JSON. Even with the.jsonURL suffix, Rails might parse the data incorrectly, leading to silent authentication failures. - Missing Devise Controller Setup: Your custom API Sessions controller doesn't define
resource_name, so when you callsign_in(resource_name, resource),resource_nameisnil—triggering the string conversion error. - Uncaught Authentication Exceptions: Warden's
authenticate!throws aWarden::NotAuthenticatedexception on failure, which your code doesn't rescue. This leads to an unhandled server error instead of a proper 401 response.
Step-by-Step Fixes
1. Update the Homework App's API Request
Fix parameter naming, send proper JSON, and correct DOM selectors (your original code targeted parent classes instead of the input fields):
var login = document.querySelector(".login") login.addEventListener("click", function(){ // Use the correct input selectors from your form var email = document.querySelector(".mail-input") var password = document.querySelector(".pw-input") // Match the main app's expected parameter key (use `user` instead of `api_user`) let loginData = { user: { email: email.value.trim(), password: password.value.trim() } } $.ajax({ url: "http://localhost:4000/api/login.json", method: "POST", contentType: "application/json", // Explicitly set JSON content type data: JSON.stringify(loginData), // Convert object to valid JSON string success: function(response){ console.log("Login successful:", response) window.location.replace("http://localhost:3000/") }, error: function(xhr){ console.error("Login failed:", xhr.responseJSON) } }) })
2. Fix the Main App's Sessions Controller
Update the controller to handle exceptions, define resource_name, and clean up control flow:
class Api::SessionsController < ApplicationController include Devise::Controllers::Helpers # Import Devise helper methods skip_before_action :verify_authenticity_token # Skip CSRF checks for API requests def create unless request.format == :json sign_out render status: 406, json: { message: "JSON requests only." } return end begin # Authenticate with Warden, catching failures to avoid 500 errors resource = warden.authenticate!(auth_options) rescue Warden::NotAuthenticated render status: 401, json: { response: "Access denied." } return end # Use explicitly defined resource_name to prevent nil errors sign_in(resource_name, resource) respond_with resource, location: after_sign_in_path_for(resource) do |format| format.json { render json: { success: true, jwt: current_token, response: "Authentication successful" } } end end private # Define your resource name (match your main app's user model, e.g., :user) def resource_name :user end # Configure Warden authentication scope def auth_options { scope: resource_name } end end
3. Verify Routes & CORS Configuration
- Routes: Ensure your main app's
config/routes.rbhas the correct API login route:namespace :api do post 'login', to: 'sessions#create' end - CORS: Since your apps run on different ports, enable cross-origin requests in the main app:
- Add the
rack-corsgem to yourGemfileand runbundle install. - Create/update
config/initializers/cors.rb:Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins 'http://localhost:3000' # Your homework app's URL resource '*', headers: :any, methods: [:get, :post, :put, :patch, :delete, :options, :head] end end
- Add the
After applying these changes, test the login flow again—you should no longer see the 500 error, and authentication should work as expected.
内容的提问来源于stack exchange,提问作者diego
相关产品推荐
相关产品推荐

