Ruby on rails ActiveRecord虚拟属性作为记录属性处理
我遇到了to_json无法呈现虚拟属性的问题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\
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">