1

子クラスが仮想フィールドを宣言できるようにする、かなりユニークなクラスがあります。子は、次のように親クラスのメソッドを呼び出すことにより、XMLとして格納された仮想フィールドを宣言できます。

class Child1 < Parent
  create_xml_field ["readings", "usage"]
end

私は厄介な回避策を介してそれを機能させることができました。create_xml_fieldメソッドは、フィールド名をクラス変数に格納します(以下を参照)。init_xml_fieldsメソッドは、after_initializeメソッド内から呼び出されます

class Parent < ActiveRecord::Base

  def self.create_xml_field(fields)
    @@xml_fields[self.name] = fields
  end

  def init_xml_fields(xml_fields)
    xml_fields.each do |f|
      f=f.to_sym
      self.class_eval do
        define_method(f) { ... } # define getter
        define_method(f) { ... } # define setter
        attr_accessible(f)       # add to mass assign OK list, does not seem to work!
      end
    end
  end

  protected
    def after_initialize
      init_xml_fields
    end
end

やっかいなえ?私は誇りに思っていませんが、それを機能させるのに苦労しています。また、回避策は、フォームパラメータの一括割り当てでは機能しません。

子クラスでの一括割り当てを許可するためにattr_acessibleを動的に呼び出した経験はありますか?前もって感謝します!

この投稿はわかりやすくするために編集されました。

4

2 に答える 2

1

アクセサメソッドを作成し、それらをattr_accessiblesとして設定するメタプログラミング部分を実装する方法は次のとおりです。

私は、個人的な十字軍として、XMLではなくYAMLを使用しています。私は先に進んで、YAMLに向けてあなたを少しずつ動かすために、不要なシリアル化の部分を実装しました。

require 'yaml'
require 'rubygems'
require 'active_support'
require 'active_record'

module Yamlable
  def self.included m
    m.extend ClassMethods
  end

  module ClassMethods
    def add_yaml_fields *args
      write_inheritable_array(:yaml_fields, args)
      attr_accessor(*args)
      attr_accessible(*args)
      before_save :serialize_yaml_fields
    end
  end

  def serialize_yaml_fields
    self.yamlable_column = read_inheritable_attribute(:yaml_fields)\
      .inject({}) { |h, a| h[a] = send(a); h }.to_yaml
  end

  def initialize(*args)
    super
    YAML::load(yamlable_column).each { |k, v| send("#{k}=", v) }
  end
end

class ParentModel < ActiveRecord::Base
  include Yamlable
  add_yaml_fields :foo, :bar
end

class ChildModel < ParentModel
end

# look, they're there:
y ChildModel.read_inheritable_attribute(:yaml_fields)

ここで、特定のコードが機能しなかった理由を知りたい場合は、さらに多くのコードを投稿する必要があります。


おそらく、クラスの継承可能な属性について少し拡張する必要があります。それらはクラス変数に少し似ており、クラスインスタンス変数に少し似ています。

クラスで継承可能な属性を定義すると、そのすべてのサブクラスがそれを共有します。ただし、子クラスで上記の属性を更新すると、この子クラスは元の属性をコピーして更新するため、更新はその属性専用であり、継承チェーン内の他のクラスには影響しません。

通常のwrite_inheritable_attributeメソッドでは、子クラスに設定すると、親からの値が上書きされるだけです。継承可能な配列とハッシュを使用write_inheritable_*して、親クラスの値に連結/マージします。


したがって、実際には、私のadd_yaml_fields作品は次のようになります。

class Parent
  add_yaml_attributes :foo

class Child1 < Parent
  add_yaml_attributes :bar

class Child2 < Parent
  add_yaml_attributes :baz

これにより、各クラスのyaml属性は次のようになります。

  • 親:foo
  • 子1:foo、bar
  • Child2:foo、baz
于 2009-05-02T11:13:46.803 に答える