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
相关产品推荐
相关产品推荐

