如何将字符串标识符存储到模型属性
我使用Virtus来创建表示Salesforce对象的模型。如何将字符串标识符存储到模型属性
我正在尝试创建具有友好名称的属性,这些名称用于访问可用于为该变量检索标识符“字符串”的值和方法。
Object.attribute #=> "BOB"
Object.get_identifier(:attribute_name) #=> "KEY"
# OR something like this
Object.attribute.identifier #=> "KEY"
友好名称用作getter/setter和一个标识符,我可以存储与API名称对应的每个属性。
下面是一个例子:
c.case_number #=> 'XXX'
c.case_number_identifier #=> 'Case_Number__c'
我能延伸Virtus::Attribute:
class Case
include Virtus.model
attribute :case_number, String, identifier: 'Case_Number__c'
end
c = Case.new(case_number: 'XXX')
c.case_number #=> 'XXX'
c.case_number.identifier #=> 'Case_Number__c'
或者,代替具有在属性本身的方法,可能是次级方法获取每个标识符集创建并添加这个?如果是这样,我不确定如何去做。
猴子肯定了Virtus打补丁Attribute
类是一种选择。
但是,深入到库的内部使您容易在该库的源代码的私有部分中进行重构。
相反,您可以使用封装此功能的辅助模块。这里有一个建议,如何:
require 'virtus'
# Put this helper module somewhere on your load path (e.g. your project's lib directory)
module ApiThing
def self.included(base)
base.include Virtus.model
base.extend ApiThing::ClassMethods
end
module ClassMethods
@@identifiers = {}
def api_attribute(attr_name, *virtus_args, identifier:, **virtus_options)
attribute attr_name, *virtus_args, **virtus_options
@@identifiers[attr_name.to_sym] = identifier
end
def identifier_for(attr_name)
@@identifiers.fetch(attr_name.to_sym){ raise ArgumentError, "unknown API attribute #{attr_name.inspect}" }
end
end
def identifier_for(attr_name)
self.class.identifier_for(attr_name)
end
end
# And include it in your API classes
class Balls
include ApiThing
api_attribute :color, String, identifier: 'SOME__fancy_identifier'
api_attribute :number, Integer, identifier: 'SOME__other_identifier'
api_attribute :size, BigDecimal, identifier: 'THAT__third_identifier'
end
# The attributes will be registered with Virtus – as usual
puts Balls.attribute_set[:color].type #=> Axiom::Types::String
puts Balls.attribute_set[:number].type #=> Axiom::Types::Integer
puts Balls.attribute_set[:size].type #=> Axiom::Types::Decimal
# You can use the handy Virtus constructor that takes a hash – as usual
b = Balls.new(color: 'red', number: 2, size: 42)
# You can access the attribute values – as usual
puts b.color #=> "red"
puts b.number #=> 2
puts b.size #=> 0.42e2
puts b.durability #=> undefined method `durability' [...]
# You can ask the instance about identifiers
puts b.identifier_for :color #=> "SOME__fancy_identifier"
puts b.identifier_for :durability #=> unknown API attribute :durability (ArgumentError)
# And you can ask the class about identifiers
puts Balls.identifier_for :color #=> "SOME__fancy_identifier"
puts Balls.identifier_for :durability #=> unknown API attribute :durability (ArgumentError)
你不需要了Virtus为了实现你的API标识符。一个类似的帮手模块可以只注册attr_accessor
而不是Virtus属性。
但是,Virtus还有其他方便的功能,如散列构造函数和属性转换。如果你不介意没有这些功能或找到替代品,放弃Virtus应该不成问题。
HTH! :)
问题解决。这很棒!谢谢 –
呀,你已经延长Virtus::Attribute
,我能得到它一起工作:
module Virtus
class AttributeSet < Module
def define_identifier(attribute, method_name, visibility, identifier)
define_method(method_name) { identifier }
send(visibility, method_name)
end
end
class Attribute
def define_accessor_methods(attribute_set)
attribute_set.define_reader_method(self, name, options[:reader])
attribute_set.define_writer_method(self, "#{name}=", options[:writer])
attribute_set.define_identifier(self, "#{name}_identifier", options[:reader], options[:identifier])
end
end
end
这可能进行重构,但你可以c.case_number_identifier
'send(visibility,method_name)'做什么? – Raffael
我复制了[define_reader_method](https://github.com/solnic/virtus/blob/master/lib/virtus/attribute_set.rb#L133)中的代码,使其一致。 [send](http://apidock.com/ruby/Object/send)调用方法,也许virtus重写'send'方法以在'public_send'中转换,因为在这种情况下'visibility'是公开的。 – MaicolBen
谢谢你的代码!这两个答案都解决了这个问题。 –
Jaison,这个问题上的赏金发生了什么?它好像只是消失在稀薄的空气中?请帮助我理解。 – Raffael
我不知道!我试图弄清楚为什么赏金从未完成。我设置了另一个赏金,我会在24小时等待时间后挂钩它 –