英文:
How to persist session in rails API only app
问题
我对Ruby on Rails还不太熟悉,但我可以帮你翻译你提供的代码和问题。以下是翻译的内容:
我对Ruby on Rails还不太熟悉,我想在Rails 6的API应用中添加会话(sessions)功能,以便在会话中获取current_cart
的ID。如果会话中不存在该ID,则创建一个新的购物车并将ID存储在会话中。
- 我想知道是否有比添加会话更好的选择?例如使用JWT令牌。
- 我正在遵循Rails敏捷Web开发书籍的指导,但我只在Rails API模式下进行操作。
以下是我的application.rb文件:
# frozen_string_literal: true
require_relative 'boot'
require 'rails'
# Pick the frameworks you want:
require 'active_model/railtie'
require 'active_job/railtie'
require 'active_record/railtie'
require 'active_storage/engine'
require 'action_controller/railtie'
require 'action_mailer/railtie'
require 'action_mailbox/engine'
require 'action_text/engine'
require 'action_view/railtie'
require 'action_cable/engine'
require 'sprockets/railtie'
# require "rails/test_unit/railtie"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module DepotApi
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.1
# skip verifying users on logout
config.to_prepare do
Devise::SessionsController.skip_before_action :verify_signed_out_user, only: :destroy
end
# Configuration for the application, engines, and railties goes here.
#
# These settings can be overridden in specific environments using the files
# in config/environments, which are processed later.
#
# config.time_zone = "Central Time (US & Canada)"
config.eager_load_paths << Rails.root.join('lib')
# Only loads a smaller set of middleware suitable for API only apps.
# Middleware like session, flash, cookies can be added back manually.
# Skip views, helpers and assets when generating a new resource.
config.api_only = true
config.app_generators.scaffold_controller = :scaffold_controller
# Middleware for ActiveAdmin
config.middleware.use Rack::MethodOverride
config.middleware.use ActionDispatch::Flash
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore
end
end
以下是我的Line_items控制器:
# frozen_string_literal: true
class LineItemsController < ApiController
include CurrentCart
before_action :set_cart, only: [:create]
before_action :set_line_item, only: %i[show update destroy]
# GET /line_items
# GET /line_items.json
def index
@line_items = LineItem.all
end
# GET /line_items/1
# GET /line_items/1.json
def show; end
# POST /line_items
# POST /line_items.json
def create
product = Product.find(params[:product_id])
@line_item = @cart.add_product(product)
if @line_item.save
render :show, status: :created, location: @line_item
else
render json: @line_item.errors, status: :unprocessable_entity
end
end
# Increasing quantity
def add_quantity
@line_item.quantity += 1
@line_item.save
end
# decreasing quantity
def reduce_quantity
@line_item.quantity > 1
@line_item.quantity -= 1
@line_item.save
end
# PATCH/PUT /line_items/1
# PATCH/PUT /line_items/1.json
def update
if @line_item.update(line_item_params)
render :show, status: :ok, location: @line_item
else
render json: @line_item.errors, status: :unprocessable_entity
end
end
# DELETE /line_items/1
# DELETE /line_items/1.json
def destroy
@line_item.destroy
end
private
# Use callbacks to share common setup or constraints between actions.
def set_line_item
@line_item = LineItem.find(params[:id])
end
# Only allow a list of trusted parameters through.
def line_item_params
params.require(:line_item).permit(:product_id)
end
end
@cart
的值由我包含的当前模块设置。
以下是我的CurrentCart模块,我在其中设置了会话:
module CurrentCart
private
def set_cart
@cart = Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
@cart = Cart.create
session[:cart_id] = @cart.id
end
end
除了activeadmin之外,我的所有API控制器都继承自这个ApiController:
class ApiController < ActionController::API
end
以下是我的application controller:
# frozen_string_literal: true
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by using :null_session
protect_from_forgery with: :null_session
before_action :configure_permitted_parameters, if: :devise_controller?
rescue_from CanCan::AccessDenied do |_exception|
render json: { error: 'Access denied' }, status: :forbidden
end
def authenticate_admin_user!
if admin_user_signed_in?
admin_root_path
else
new_admin_user_session_path
end
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: %i[user_name email role])
devise_parameter_sanitizer.permit(:sign_in, keys: %i[user_name email role])
end
end
希望这可以帮助到你!如果你有任何其他问题,请随时问我。
英文:
I am pretty new to ruby on rails, I want to add sessions back to rails 6 API app such that I get the current_cart
id in session, if the the id does not exist in session, it goes on to create a new cart and store the id in session.
- I would like to know if there is another better option than adding sessions back? i.e. like using JWT tokens.
- I am following rails agile web development book, but I did it in rails API mode only.
Below is my application.rb
# frozen_string_literal: true
require_relative 'boot'
require 'rails'
# Pick the frameworks you want:
require 'active_model/railtie'
require 'active_job/railtie'
require 'active_record/railtie'
require 'active_storage/engine'
require 'action_controller/railtie'
require 'action_mailer/railtie'
require 'action_mailbox/engine'
require 'action_text/engine'
require 'action_view/railtie'
require 'action_cable/engine'
require 'sprockets/railtie'
# require "rails/test_unit/railtie"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module DepotApi
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.1
# skip verifying users on logout
config.to_prepare do
Devise::SessionsController.skip_before_action :verify_signed_out_user, only: :destroy
end
# Configuration for the application, engines, and railties goes here.
#
# These settings can be overridden in specific environments using the files
# in config/environments, which are processed later.
#
# config.time_zone = "Central Time (US & Canada)"
config.eager_load_paths << Rails.root.join('lib')
# Only loads a smaller set of middleware suitable for API only apps.
# Middleware like session, flash, cookies can be added back manually.
# Skip views, helpers and assets when generating a new resource.
config.api_only = true
config.app_generators.scaffold_controller = :scaffold_controller
# Middleware for ActiveAdmin
config.middleware.use Rack::MethodOverride
config.middleware.use ActionDispatch::Flash
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore
end
end
Below is my Line_items controller
# frozen_string_literal: true
class LineItemsController < ApiController
include CurrentCart
before_action :set_cart, only: [:create]
before_action :set_line_item, only: %i[show update destroy]
# GET /line_items
# GET /line_items.json
def index
@line_items = LineItem.all
end
# GET /line_items/1
# GET /line_items/1.json
def show; end
# POST /line_items
# POST /line_items.json
def create
product = Product.find(params[:product_id])
@line_item = @cart.add_product(product)
if @line_item.save
render :show, status: :created, location: @line_item
else
render json: @line_item.errors, status: :unprocessable_entity
end
end
# Increasing quantity
def add_quantity
@line_item.quantity += 1
@line_item.save
end
# decreasing quantity
def reduce_quantity
@line_item.quantity > 1
@line_item.quantity -= 1
@line_item.save
end
# PATCH/PUT /line_items/1
# PATCH/PUT /line_items/1.json
def update
if @line_item.update(line_item_params)
render :show, status: :ok, location: @line_item
else
render json: @line_item.errors, status: :unprocessable_entity
end
end
# DELETE /line_items/1
# DELETE /line_items/1.json
def destroy
@line_item.destroy
end
private
# Use callbacks to share common setup or constraints between actions.
def set_line_item
@line_item = LineItem.find(params[:id])
end
# Only allow a list of trusted parameters through.
def line_item_params
params.require(:line_item).permit(:product_id)
end
end
- The value of
@cart
is set by the current module I have included.
Below is my Currentcart
module where I set the session from
module CurrentCart
private
def set_cart
@cart = Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
@cart = Cart.create
session[:cart_id] = @cart.id
end
end
All my API controllers are extending from this apiController
except activeadmin
class ApiController < ActionController::API
end
Below is my application controller
# frozen_string_literal: true
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by using :null_session
protect_from_forgery with: :null_session
before_action :configure_permitted_parameters, if: :devise_controller?
rescue_from CanCan::AccessDenied do |_exception|
render json: { error: 'Access denied' }, status: :forbidden
end
def authenticate_admin_user!
if admin_user_signed_in?
admin_root_path
else
new_admin_user_session_path
end
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: %i[user_name email role])
devise_parameter_sanitizer.permit(:sign_in, keys: %i[user_name email role])
end
end
答案1
得分: 0
我终于找到了一个解决方案,让两个应用程序连接起来,一个是create react app,另一个是rails api。首先,我需要在rails api中添加回话(sessions)的支持。
config.api_only = true
config.app_generators.scaffold_controller = :scaffold_controller
# Middleware for ActiveAdmin
config.middleware.use Rack::MethodOverride
config.middleware.use ActionDispatch::Flash
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore
然后,在create react app中,我在package.json
中添加了以下设置:
"proxy": "http://127.0.0.1:4000"
接下来,我将前端(create react app)的所有路由更改如下:
将http://127.0.0.1.400/products
更改为/products
这样,你就可以在前端获取会话中的任何内容了。
英文:
- I finally a solution, for the two apps to connect, the create react app and a rails api i needed to first add back sessions to the rails api
config.api_only = true
config.app_generators.scaffold_controller = :scaffold_controller
# Middleware for ActiveAdmin
config.middleware.use Rack::MethodOverride
config.middleware.use ActionDispatch::Flash
config.middleware.use ActionDispatch::Cookies
config.middleware.use ActionDispatch::Session::CookieStore
-
then in create react app i added this setting in
package.json
"proxy": "http://127.0.0.1:4000"
-
Then all my routes on the front end (create react app) where changed as follow
http://127.0.0.1.400/products
to/products
-
Their you can get anything from session on the front end
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论