我来自.NET世界,我正试图弄清楚在多层应用程序中跨层传递对象的'Rails方式'。
我正在撰写多运营商定价API。基本上在我的价格控制器中,我可以访问以下参数 params [:carrier] , params [:address_from] , params [:address_to] , params [:container_type] 等。我有一个验证库,一个合规性库和一个价格查找器库,每个库都处理一个参数的子集。
在.NET中,params将被包含在数据传输对象(DTO)或契约中。在调用任何库之前,它们将被转换为域对象(DO),并且每个库都可以在DO上工作,从而避免在DTO上紧密耦合。 Ruby编程推荐使用'duck typing',因此我的库可以直接在params上工作(即使你会访问符号而不是对象/属性)。或者我应该将我的params编组到一个PriceRequest对象中,让我的库工作在PriceRequest类型上吗?
选项1:
class PricesController < ApplicationController
def get
CarrierValidator.validate(params)
...
end
end
class CarrierValidator
def self.validate(params)
raise CarrierError if !Carrier.find_by_name(params[:carrier_name]).exists?
end
end
选项2:
class PricesController < ApplicationController
def get
pricesRequest = PricesRequest.new(carrier_name: params[:carrier_name], ...)
pricesRequest.validate
...
end
end
class PriceRequest
attr_accessor : ...
def initalize
...
end
def validate
CarrierValidator.validate(self.carrier_name)
end
end
class CarrierValidator
def self.validate(carrier_name)
raise CarrierError if !Carrier.find_by_name(carrier_name).exists?
end
end
TIA,
Ĵ
答案 0 :(得分:1)
您应该创建一个类型。我会使用 ActiveModel 来封装数据(属性)&amp;业务逻辑(验证和一些特定于层的处理数据的方法)。
基本上,您希望能够在控制器中执行Rails-y操作:
def get
price_request = PriceRequest.new(params[:price_request])
if price_request.valid?
# do something like redirect or render
else
# do something else
end
end
所以你要声明:
class PriceRequest
include ActiveModel::Model
attr_accessor :carrier, :address_from, :address_to, :container_type
validates :carrier, presence: true
validate :validate_address_from
def validate_address_from
# do something with errors.add
end
# and so on
这是一个很好的起点:http://edgeguides.rubyonrails.org/active_model_basics.html
API中的更多详细信息:http://api.rubyonrails.org/classes/ActiveModel/Model.html
希望指出你正确的方向......