2017-03-02 16 views
9

Tôi đang sử dụng Virtus để tạo mô hình đại diện cho đối tượng Salesforce.Cách lưu trữ số nhận dạng chuỗi vào thuộc tính mô hình

Tôi đang cố gắng tạo thuộc tính có tên thân thiện được sử dụng để truy cập giá trị và phương pháp mà tôi có thể sử dụng để truy xuất số nhận dạng "Chuỗi" cho biến đó.

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

Tên thân thiện được sử dụng làm getter/setter và số nhận dạng mà tôi có thể lưu trữ mỗi thuộc tính tương ứng với tên API.

Dưới đây là một ví dụ:

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' 

Hoặc, thay vì có một phương pháp trên thuộc tính riêng của mình, có thể là một phương pháp phổ thông được tạo ra cho mỗi bộ định danh:

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

Tôi có thể mở rộng Virtus::Attribute và thêm cái này? Nếu vậy, tôi không chắc chắn về cách đi về nó.

+0

Jaison, điều gì đã xảy ra với tiền thưởng cho câu hỏi này? Có vẻ như nó chỉ biến mất vào không khí mỏng? Xin hãy giúp tôi hiểu. – Raffael

+0

tôi không biết! Tôi cố gắng tìm ra lý do tại sao tiền thưởng không bao giờ hoàn thành. Tôi thiết lập một tiền thưởng khác và tôi sẽ treo nó lên sau thời gian chờ 24 giờ –

Trả lời

5

khỉ vá lớp Attribute Virtus' chắc chắn là một lựa chọn .
Tuy nhiên, việc truy cập vào nội bộ của thư viện sẽ làm cho bạn dễ bị tổn thương do tái cấu trúc trong phần riêng tư của mã nguồn của thư viện đó.

Thay vào đó, bạn có thể sử dụng mô-đun trợ giúp đóng gói tính năng này. Dưới đây là một đề xuất về cách:

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) 

Bạn không cần Virtus để triển khai mã định danh API của bạn. Một mô-đun trợ giúp tương tự chỉ có thể đăng ký attr_accessor s thay vì các thuộc tính Virtus.
Tuy nhiên, Virtus có các tính năng tiện dụng khác như hàm băm và thuộc tính. Nếu bạn không nhớ sống mà không có những tính năng này hoặc tìm kiếm thay thế, vứt bỏ Virtus không phải là một vấn đề.

HTH! :)

+0

Sự cố được giải quyết. điều đó thật tuyệt! cảm ơn bạn –

3

Yeah, bạn đã để mở rộng Virtus::Attribute, tôi có thể nhận được nó để làm việc với:

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 

Điều này có thể được refactored nhưng bạn có thể c.case_number_identifier

+0

'send (visibility, method_name)' làm gì? – Raffael

+0

Tôi đã sao chép mã từ [define_reader_method] (https://github.com/solnic/virtus/blob/master/lib/virtus/attribute_set.rb#L133), để làm cho nó phù hợp. [send] (http://apidock.com/ruby/Object/send) gọi phương thức, có thể virtus ghi đè phương thức 'send' để chuyển đổi trong' public_send' vì 'hiển thị' là công khai trong trường hợp này. – MaicolBen

+1

Cảm ơn bạn đã nhập mã này! Cả hai câu trả lời giải quyết vấn đề này. –

Các vấn đề liên quan