在我的Application Controller中,我根据地理位置设置了一个货币变量:
class ApplicationController < ActionController::Base
before_action :currency
protected
def currency
cookies[:country] ||= request.location.country
case cookies[:country]
when "MY"
c = "MYR"
when "SG"
c = "SGD"
else
c = "USD"
end
@currency = Currency.find_by(name: c)
end
end
我有使用价格方法的模型产品和多种货币,多种价格,即:一种产品可以采用自定义定价的多种货币。
class Product < ApplicationRecord
has_many :prices
has_many :currencies, through: :prices
def price
# how to access @currency?
end
end
class Price < ApplicationRecord
belongs_to :product
belongs_to :currency
end
class Currency < ApplicationRecord
has_many :prices
has_many :products, through: :prices
end
在Model Product.price中访问@currency的最佳方法是什么?或者如何告诉方法仅以@currency返回价格?这可能不是最好的处理方法,请提出建议。
答案 0 :(得分:3)
您的情况有些落后,因此您正在尝试解决错误的问题。模型不应该试图从控制器层获取信息,控制器应该将信息发送到模型中:
class Product < ApplicationRecord
#...
def price_in(currency)
# Access the associations however you need to and handle missing
# information however fits your application in here...
end
end
,然后在您的控制器或视图中:
price = product.price_in(@currency)
您应该能够从任何地方(控制器,Rake任务,作业,控制台等)调用模型上的方法,而不必担心所有特定于请求的状态。
答案 1 :(得分:1)
不应该。这样做违反了许多设计原则,只会使自己沮丧。
您的模型不应在乎控制器的上下文。它应该只关心与自身相关的数据。
您可以使用ActiveModel::Attributes
API。
在您的模型中:
class Product < ApplicationRecord
has_many :prices
has_many :currencies, through: :prices
attribute :currency
def price
self.currency
end
end
在您的控制器中:
class ProductsController < ApplicationController
def show
@product = Product.find(params[:id])
@product.currency = @currency
end
end
使用ActiveModel::Attributes
API可以做更多的事情,例如设置默认值,运行验证,甚至设置对象的类型(布尔/真/假,整数,字符串等)。它的行为就像您在模型上的常规属性一样,只是它们不受数据库支持。
有关此出色的API https://apidock.com/rails/ActiveRecord/Attributes/ClassMethods/attribute
的更多信息答案 2 :(得分:0)
查看this answer,了解有关如何访问模型中的cookie的信息。但是您应该考虑将此方法移出控制器,并移入Currency类,这似乎更合逻辑。然后,您可以从Product类中将方法称为Currency.get_currency。