4

ドキュメントを調べましたが、これについての具体的な方法が見つかりません。いくつかの動的属性をモデルに既に追加しており、それらすべてを反復できるようにしたいと考えています。

したがって、具体的な例として:

class Order
  include Mongoid::Document

  field :status, type: String, default: "pending"
end

そして、次のことを行います。

Order.new(status: "processed", internal_id: "1111") 

そして後で戻ってきて、すべての動的属性のリスト/配列を取得できるようにしたいと考えています (この場合は「internal_id」です)。

私はまだ掘り下げていますが、他の誰かがすでにこれを解決しているかどうか聞いてみたいです.

4

6 に答える 6

5

モデルに次のようなものを含めるだけです。

module DynamicAttributeSupport

  def self.included(base)
    base.send :include, InstanceMethods
  end

  module InstanceMethods
    def dynamic_attributes
      attributes.keys - _protected_attributes[:default].to_a - fields.keys
    end

    def static_attributes
      fields.keys - dynamic_attributes
    end
  end

end

これに対応する仕様は次のとおりです。

require 'spec_helper'

describe "dynamic attributes" do

  class DynamicAttributeModel
    include Mongoid::Document
    include DynamicAttributeSupport
    field :defined_field, type: String
  end

  it "provides dynamic_attribute helper" do
    d = DynamicAttributeModel.new(age: 45, defined_field: 'George')
    d.dynamic_attributes.should == ['age']
  end

  it "has static attributes" do
    d = DynamicAttributeModel.new(foo: 'bar')
    d.static_attributes.should include('defined_field')
    d.static_attributes.should_not include('foo')
  end

  it "allows creation with dynamic attributes" do
    d = DynamicAttributeModel.create(age: 99, blood_type: 'A')
    d = DynamicAttributeModel.find(d.id)
    d.age.should == 99
    d.blood_type.should == 'A'
    d.dynamic_attributes.should == ['age', 'blood_type']
  end
end
于 2012-11-07T01:34:57.720 に答える
5

これにより、特定のレコード x の動的フィールド名のみが得られます。

dynamic_attribute_names = x.attributes.keys - x.fields.keys

追加の Mongoid 機能を使用する場合は、それらの機能に関連付けられたフィールドを差し引く必要がありますMongoid::Versioning

dynamic_attribute_names = (x.attributes.keys - x.fields.keys) - ['versions']

動的属性のみのキーと値のペアを取得するには:

attributes() の結果を必ず複製してください。そうしないと x を変更してしまいます!!

attr_hash = x.attributes.clone  #### make sure to clone this, otherwise you modify x !!
dyn_attr_hash = attr_hash.delete_if{|k,v| ! dynamic_attribute_names.include?(k)}

または1行で:

x.attributes.clone.delete_if{|k,v| ! dynamic_attribute_names.include?(k)}
于 2012-07-22T23:07:44.333 に答える
1

それで、私がやったことはこれです。それが最善の方法かどうかはわかりませんが、探している結果が得られるようです。

class Order
  def dynamic_attributes
    self.attributes.delete_if { |attribute| 
      self.fields.keys.member? attribute 
    }
  end
end

属性はオブジェクトの実際の属性のリストのように見えますが、フィールドは事前定義されたフィールドのハッシュのように見えます。ドキュメントでそれを正確に見つけることができませんでしたが、他の誰かがより良い方法を知らない限り、今のところそれを使用します!

于 2012-07-05T14:22:27.850 に答える
0

クローン アプローチが気に入ったかどうかわからないので、クローン アプローチも作成しました。これから、コンテンツのハッシュも簡単に作成できます。これは単にすべての動的フィールドを出力するだけです (フラット構造)

 (d.attributes.keys - d.fields.keys).each {|a| puts "#{a} = #{d[a]}"};
于 2012-08-27T13:34:21.340 に答える
0

.methods または .instance_variables を試してください

于 2012-07-04T00:07:40.997 に答える
0

上記の解決策のいずれも機能させることができませんでした (各モデルにコードのスラブとスラブを追加する必要がなかったため、何らかの理由でattributes、モデル インスタンスにメソッドが存在しませんでした。 :/) というわけで、これを行うために独自のヘルパーを作成することにしました。このメソッドには、動的フィールドと定義済みフィールドの両方が含まれることに注意してください。

helpers/mongoid_attribute_helper.rb :

module MongoidAttributeHelper
  def self.included(base)
    base.extend(AttributeMethods)
  end

  module AttributeMethods
    def get_all_attributes
      map = %Q{
          function() {
            for(var key in this)
            {
              emit(key, null);
            }
          }
        }

      reduce = %Q{
          function(key, value) {
            return null;
          }
        }

      hashedResults = self.map_reduce(map, reduce).out(inline: true) # Returns an array of Hashes (i.e. {"_id"=>"EmailAddress", "value"=>nil} )

      # Build an array of just the "_id"s.
      results = Array.new
      hashedResults.each do |value|
        results << value["_id"]
      end

      return results
    end
  end
end

models/user.rb :

class User
   include Mongoid::Document
   include MongoidAttributeHelper
   ...
end

このメソッドを使用する各モデルに前述の include( include MongoidAttributeHelper) を追加すると、 を使用してすべてのフィールドのリストを取得できますUser.get_all_attributes

確かに、これは最も効率的または洗練された方法ではないかもしれませんが、確実に機能します。:)

于 2015-03-18T20:28:52.650 に答える