如何自动向rails模块中的模型对象添加和序列化虚拟属性?

How to automatically add and serialize virtual attribute to model object in rails module?

如果 Plugin 名称为 SomePluggin,如何修饰 Plugin 对象以自动向属性添加虚拟 page_links 属性?

示例:

@page.plugins
# As is => [#<Plugin id: 241, url: "some_url", page_id: 118>]
# As I want to be: => [#<Plugin id: 241, url: "some_url", page_links: "1234,main_page,articles", page_id: 118>]

当前代码:

module Cms
  class SomePluggin
    def initialize(plugin)
      @url = plugin.url

      #it doesn't work
      plugin.page_links = "1234,main_page,articles"
      plugin.attributes.merge!("page_links" => "1234,main_page,articles")
      #decorate = SimpleDelegator.new plugin
    end

    def get_content
      puts "content"
    end
  end

  module Pluggin
    extend ActiveSupport::Concern

    included do
      after_initialize :pluggin
    end

    delegate :get_content, to: :pluggin

    attr_writer :pluggin

    def pluggin
      @pluggin ||= "Cms::Pluggin::#{name}".camelize.constantize.new(self) # name=SomePluggin
    end
  end
end

型号:

class Plugin < ActiveRecord::Base
  attr_accessor :page_links
  belongs_to :page
  include Cms::Pluggin
end

我假设 page_links 是虚拟属性。你的代码结构比较复杂,你基本上可以在class Plugin中添加page_linkspage_links=方法初始化,但是如果你想在SomePluggin中保留这个属性,你可以这样做它是这样的:

module Cms
  class SomePluggin
    attr_accessor :page_links

    def initialize
      self.page_links = "1234,main_page,articles"
    end

    def get_content
      puts "content"
    end
  end

  module Pluggin                                                                                                                                                                         
    extend ActiveSupport::Concern

    included do
      after_initialize :wrap_object
    end

    def wrap_object
      pluggin                                                                                                                                                                            
    end
    delegate :get_content, :page_links, :page_links=, to: :pluggin

    attr_writer :pluggin

    def pluggin
      @pluggin ||= SomePluggin.new
    end                                                                                                                                                                                
  end                                                                                                                                                                                
end

这里我在SomePluggin中添加了:page_links:page_links=方法,在initialize方法中设置了初始值。

一些控制台输出:

p = Plugin.new
p.page_links # => "1234,main_page,articles"
p.page_links = '123'
p.page_links # => "123"