You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RoR电商项目实现货币切换,需指导StoreController方法开发

问题描述

我是Ruby on Rails(RoR)新手,正在开发电商类项目,需实现商品价格多货币转换功能。目前已完成以下工作:

  • 创建了商品装饰器实例:
@product_decorator = Product.includes(:category).map{|product| ProductDecorator.new(product)}
  • 数据库中创建了存储实时汇率的product_wrappers表,建表语句:
create_table :product_wrappers do |t|
  t.decimal :euro
  t.decimal :rubles
end
  • 手动修改商品价格方法后,欧元/卢布价格在视图中显示正常,但需要通过link_to传递eur/rub等参数切换货币,目前卡在StoreController的set_currency方法编写环节。已配置路由:
put '/set_currency', to: 'store#set_currency'
  • 视图切换按钮代码:
<%= link_to "USD", set_currency_path(:currency => :usd), class: "btn btn-outline-secondary" %>
<%= link_to "RUB", set_currency_path(:currency => :rub), class: "btn btn-outline-secondary" %>
<%= link_to "EUR", set_currency_path(:currency => :eur), class: "btn btn-outline-secondary" %>

解决方案

1. 匹配路由与视图请求方法

link_to默认发送GET请求,但你配置的路由是PUT方法,会导致请求不匹配,二选一调整即可:

方式一:修改路由为GET(更适合无状态的货币切换操作)

# config/routes.rb
get '/set_currency', to: 'store#set_currency'

方式二:让link_to发送PUT请求

在视图按钮中添加method: :put参数(需确保项目引入Rails UJS,默认已包含):

<%= link_to "USD", set_currency_path(:currency => :usd), class: "btn btn-outline-secondary", method: :put %>
<%= link_to "RUB", set_currency_path(:currency => :rub), class: "btn btn-outline-secondary", method: :put %>
<%= link_to "EUR", set_currency_path(:currency => :eur), class: "btn btn-outline-secondary", method: :put %>

2. 编写StoreController的set_currency方法

核心逻辑是将用户选择的货币存入会话(session),保持当前用户的货币偏好,然后重定向回原页面:

# app/controllers/store_controller.rb
class StoreController < ApplicationController
  def set_currency
    # 定义允许的货币白名单,拦截非法参数
    allowed_currencies = [:usd, :rub, :eur]
    selected_currency = params[:currency].to_sym

    # 验证并设置会话货币,非法参数则默认USD
    session[:current_currency] = allowed_currencies.include?(selected_currency) ? selected_currency : :usd

    # 重定向到上一页, fallback指定默认跳转页
    redirect_back fallback_location: root_path
  end
end

3. 在ProductDecorator中适配会话货币

修改装饰器的价格方法,读取会话中的货币设置,结合product_wrappers的汇率计算对应价格(需确保Product与ProductWrapper已建立has_one关联):

# app/decorators/product_decorator.rb
class ProductDecorator < Draper::Decorator
  delegate_all

  def formatted_price
    current_currency = session[:current_currency] || :usd
    case current_currency
    when :usd
      number_to_currency(object.price, unit: "$")
    when :eur
      euro_price = object.price * object.product_wrapper.euro
      number_to_currency(euro_price, unit: "€")
    when :rub
      rub_price = object.price * object.product_wrapper.rubles
      number_to_currency(rub_price, unit: "₽", format: "%n %u")
    end
  end
end

4. 视图中调用适配后的价格方法

在商品列表视图中,直接调用装饰器的formatted_price方法,即可自动根据会话货币显示对应价格:

<% @product_decorator.each do |product| %>
  <div class="product-item">
    <h4><%= product.name %></h4>
    <p class="price"><%= product.formatted_price %></p>
  </div>
<% end %>

内容的提问来源于stack exchange,提问作者Sash0k411

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 21:09:31