我的API的V6中有以下私有方法:
def format_rentals(rentals)
rentals.map do |rental|
{
start_time: rental.reservation_start_time.to_i,
end_time: rental.reservation_end_time.to_i
}
end
在API的V10上。
V10继承自V9,V9来自V8,依旧......
我想要一个新方法的属性。
有没有办法不将整个方法剪切并粘贴到V10上,然后添加新属性。
我不想做的事情:
def format_rentals(rentals)
rentals.map do |rental|
{
start_time: rental.reservation_start_time.to_i,
end_time: rental.reservation_end_time.to_i,
status: rental.status ### Adding this on V10
}
end
我很想打电话给super并合并到hash,到目前为止我已经尝试过了:
def format_rentals(rentals)
rentals.map do |rental|
super.merge(status: rental.status)
end
end
我可能没有正确的语法...感谢您的帮助!
答案 0 :(得分:2)
如果在超类中将块的内容提取到自己的format_rental
方法中,这非常容易:
class V9 < V8
def format_rental(rental)
{ start_time: rental.reservation_start_time.to_i,
end_time: rental.reservation_end_time.to_i
}
end
def format_rentals(rentals)
rentals.map {|rental| format_rental(rental) }
end
end
然后,在您的子类中,您只需覆盖format_rental
:
class V10 < V9
def format_rental(rental)
super.merge(status: rental.status)
# Or: super.tap {|r| r[:status] = rental.status }
end
end
super
将返回带有:start_time
和:end_time
键的哈希值;那么你只需要添加:status
密钥即可。 format_rentals
根本不需要修改。
答案 1 :(得分:1)
问题是您在传递给super
的块内调用.map
。这意味着在每次迭代中都会调用format_rentals
。您可以编写一种格式化单个记录的方法:
def format_rentals(rentals)
rentals.map { |r| format_rental(r) }
end
def format_rental(rental)
super.merge(status: rental.status)
end
或者通过积木和收益获得创意。
然而,可能是退后一步并考虑这是否是一个好解决方案的好时机 - 您的控制器是否真的要负责序列化rentals
?特别是如果您在不同版本的API中有不同的表示形式。我会考虑使用ActiveModel::Serializers
或jbuilder
。
class V9::RentalSerializer < ActiveModel::Serializer
attributes :start_time, :end_time
def start_time
object.reservation_start_time.to_i
end
def end_time
object.reservation_end_time.to_i
end
end
class V10::RentalSerializer < V9::RentalSerializer
attributes :start_time, :end_time, :status
end
但 - 根据API版本创建深层次结构也不是最佳选择。原因是它变成了一个非常精致的卡片屋,对于那些从第一天起就没有关注过这个项目的人来说,这是不可能破译的。
你可能想考虑拥有一个&#34; base&#34;它遵循当前版本和&#34;适配器&#34;旧版本的哪个backport。
class MyApi::RentalSerializerBase < ActiveModel::Serializer
attributes :start_time, :end_time, :status
def start_time
object.reservation_start_time.to_i
end
def end_time
object.reservation_end_time.to_i
end
end
class V7::RentalSerializer < MyApi::RentalSerializerBase
attributes :start_time, :end_time
# lets say version 7 has a weird bug so that end_time is in iso 8601 instead
# however since clients rely on the defect
# being there we cannot change the response
def end_time
object.reservation_end_time.iso8601
end
end
class V10::RentalSerializer < MyApi::RentalSerializerBase; end