2017-03-02 16 views
9

Salesforce nesnelerini temsil eden modeller oluşturmak için Virtus kullanıyorum.Dize tanımlayıcısını bir model özniteliğine nasıl depolanır

Bu değişken için "String" tanımlayıcısını almak için kullanabileceğim değer ve yönteme erişmek için kullanılan arkadaş isimlerine sahip öznitelikler oluşturmaya çalışıyorum.

Object.attribute #=> "BOB" 
Object.get_identifier(:attribute_name) #=> "KEY" 
# OR something like this 
Object.attribute.identifier #=> "KEY" 

kolay adı alıcı/ayarlayıcı ve API ismine karşılık gelen her bir özelliği saklayabilen tespit edicisi olarak kullanılmaktadır. İşte

bir örnek:

c.case_number #=> 'XXX' 
c.case_number_identifier #=> 'Case_Number__c' 

Ben Virtus::Attribute uzatmak Could: yerine Nitelik kendisinde bir yöntem olmasının,

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' 

Ya da, belki ikinci bir yöntem, her tanımlayıcı grubu için oluşturulan alır ve bunu ekle? Eğer öyleyse, nasıl gideceğime emin değilim.

+0

Jaison, bu sorudaki kelle ne oldu? Görünüşe göre sadece ince havaya kayboldu mu? Lütfen anlamama yardım et. – Raffael

+0

Hiçbir fikrim yok! Kendimi niçin tamamlamadığımı anlamaya çalışıyorum. Başka bir ödül kuruyorum ve 24 saat bekledikten sonra bağlayacağım –

cevap

5

Maymun kesinlikle Virtus'un Attribute sınıf yama bir seçenektir olabilir . Bununla birlikte, bir kütüphanenin içeriğine ulaşmak sizi bu kütüphanelerin kaynak kodunun özel bölümündeki refakatörlere karşı savunmasız bırakıyor. Bu özelliği kapsülleyen bir yardımcı modül kullanabilirsiniz. Bunun yerine, bu özelliği içine alan bir yardımcı modül kullanabilirsiniz.

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) 

Sen API tanımlayıcıları uygulamak amacıyla Virtus gerekmez: İşte nasıl bir öneridir. Benzer bir yardımcı modül sadece Virtus öznitelikleri yerine attr_accessor s kaydedebilir.
Ancak, Virtus, karma yapıcılar ve öznitelik dizisi gibi diğer kullanışlı özelliklere sahiptir. Eğer bu özellikler olmadan ya da yer değiştirmeden yaşarsanız, Virtus'u terketmek sorun olmaz.

HTH! :)

+0

Sorun çözüldü. bu harika! teşekkür ederim –

3

Evet, ben çalışmak için alabilir, Virtus::Attribute uzatmak ettik: Bu refactored olabilir

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 

ancak c.case_number_identifier

+0

Gönderme (görünürlük, yöntem_adı) nedir? – Raffael

+0

Kodu tutarlı hale getirmek için [define_reader_method] (https://github.com/solnic/virtus/blob/master/lib/virtus/attribute_set.rb#L133) adresinden kodu kopyaladım. [gönder] (http://apidock.com/ruby/Object/send) yöntemi çağırır, belki de 'public' deyiminde 'gönder' yöntemini geçersiz kılar çünkü 'görünürlük' bu durumda geneldir. – MaicolBen

+1

Bu kod için teşekkürler! Her iki cevap da bu problemi çözüyor. –

İlgili konular