Ruby on rails ActiveRecord虚拟属性作为记录属性处理

Ruby on rails ActiveRecord虚拟属性作为记录属性处理,ruby-on-rails,activerecord,Ruby On Rails,Activerecord,我遇到了to_json无法呈现虚拟属性的问题 class Location < ActiveRecord::Base belongs_to :event before_create :generate_oid validates_associated :event attr_accessor :event_oid def event_oid @event_oid = event.oid end end 类位置[:event\

我遇到了to_json无法呈现虚拟属性的问题

class Location < ActiveRecord::Base
    belongs_to :event
    before_create :generate_oid
    validates_associated :event

    attr_accessor :event_oid

    def event_oid
      @event_oid = event.oid
    end
end
类位置
事件\u oid不是以下程序返回的数组的一部分:

Location.first.attributes Location.first.attributes 当使用to_json自动将记录属性序列化到jason时,这对我来说尤其是一个问题。to_json忽略了我的虚拟属性

如何将虚拟属性视为实际实例属性

编辑: to_json只是将我的虚拟属性作为实际属性处理的方法的一个示例。

to_json(:methods=>[:event\u oid])怎么样?
,这样做有效吗?

只需自己实现to#u json即可:

class Location < ActiveRecord::Base
  def to_json(options={})
    options[:methods] ||= []
    options[:methods] << :event_oid
    super(options)
  end
end
类位置选项[:方法]要修改属性哈希。这里有一些额外的代码,以确保您关心的属性可以与to_json或其他依赖于对象加载属性的方法一起使用

class Location < ActiveRecord::Base
    belongs_to :event
    before_create :generate_oid
    validates_associated :event

    after_save :event_oid

    attr_accessor :event_oid

    def event_oid
      @event_oid = @attributes["event_oid"] = event.oid if event.nil?
    end       

    def after_initialize
      event_oid
    end


end
类位置
使用json和许多其他方法,根据对象属性生成事物列表。它在对象初始化时使用数据库表和名称填充,不幸的是实例变量不会更新此哈希

另外,如果你有许多属性想以这种方式使用,那么这并不是很枯燥。您可以使用一个符号数组、确定性方法名称和一个class_eval块将此过程一次应用于多个符号

警告 我们正在搞乱rails的内部结构。很难说这会导致其他事情失败。我只测试了save和to_json,当属性散列包含的键不是列名时,这两种方法都有效。所以使用它的风险由你自己承担。

在将
修改为
修改为
作为

def as_json(options={})
  options[:methods] ||= []
  options[:methods] << :class_to_s
  super(options)
end
def as_json(选项={})
选项[:方法]| |=[]
选项[:方法]
如下文所述:

在控制器中,只需使用:

format.json { render json: @location.to_json(:methods => :event_oid) }

这是一个老问题,但OP提出的问题现在是可能的,只要你知道怎么做就简单了。 这里是一个完整的可运行示例,但您需要的一切都在类位置。
attribute
语句扩展模型的属性,初始化后的
语句负责赋值

require 'active_record'  

ActiveRecord::Base.establish_connection(  
  :adapter=> "sqlite3",  
  :database=> ":memory:"  
)  

ActiveRecord::Schema.define do
  create_table :events do |table|
    table.column :name, :string
  end
  create_table :locations do |table|
    table.column :name, :string
    table.column :event_id, :integer
  end
end

class Event < ActiveRecord::Base
  has_one :location
end

class Location < ActiveRecord::Base
  belongs_to :event
  attribute :event_name, :string

  after_initialize do
    self.event_name = event.name
  end
end

Event.create(name: 'Event1')
Location.create(name: 'Location1', event_id: 1)
p Model.attribute_names
p Event.first
p Event.first.location

#["id", "name", "event_id", "event_name"]
#<Event id: 1, name: "Event1">
#<Location id: 1, name: "Location1", event_id: 1, event_name: "Event1">
需要“活动记录”
ActiveRecord::Base.建立\u连接(
:adapter=>“sqlite3”,
:数据库=>“:内存:”
)  
ActiveRecord::Schema.define do
创建|表:事件做|表|
table.column:name,:string
结束
创建|表:位置do|表|
table.column:name,:string
table.column:event_id,:integer
结束
结束
类事件
这确实有效,我可能不得不使用它。我只是希望有一种方法可以欺骗ActiveRecord,使其认为event_oid相当于locations表中的一列。我还希望其他方法将虚拟属性视为合法属性,而不是json。to\json只是一个例子。我应该说得更清楚,谢谢。我一直想知道怎么做。这会派上用场的。
require 'active_record'  

ActiveRecord::Base.establish_connection(  
  :adapter=> "sqlite3",  
  :database=> ":memory:"  
)  

ActiveRecord::Schema.define do
  create_table :events do |table|
    table.column :name, :string
  end
  create_table :locations do |table|
    table.column :name, :string
    table.column :event_id, :integer
  end
end

class Event < ActiveRecord::Base
  has_one :location
end

class Location < ActiveRecord::Base
  belongs_to :event
  attribute :event_name, :string

  after_initialize do
    self.event_name = event.name
  end
end

Event.create(name: 'Event1')
Location.create(name: 'Location1', event_id: 1)
p Model.attribute_names
p Event.first
p Event.first.location

#["id", "name", "event_id", "event_name"]
#<Event id: 1, name: "Event1">
#<Location id: 1, name: "Location1", event_id: 1, event_name: "Event1">