我有一个模型,有一个表。Download
有一个名为downloads
的字段,该字段将ip地址存储为整数我想建立一个downloads
模型,但是没有ip_addresses表,所以我可以做如下事情
Download.find(1).ip_address.to_s # '127.0.0.1'
Download.find(1).ip_address.to_i # 2130706433
Download.find(1).ip_address.downloads # SELECT * FROM downloads WHERE ip_address='2130706433'
IpAddress.find(2130706433).downloads # SELECT * FROM downloads WHERE ip_address='2130706433'
我希望它表现得像:
class Download < ActiveRecord::Base
belongs_to :ip_address, :foreign_key => :ip_address
end
class IpAddress < ActiveRecord::Base
set_primary_key :ip_address
has_many :downloads, :foreign_key => :ip_address
end
但是没有无用的ip地址表。
这可能吗?
编辑
我发现ruby已经有了一个IPAddr class。
所以我这么做了:
require 'ipaddr'
class Download < ActiveRecord::Base
attr_accessible :ip, ...
def ip
@ip ||= IPAddr.new(read_attribute(:ip), Socket::AF_INET)
end
def ip=(addr)
@ip = IPAddr.new(addr, Socket::AF_INET)
write_attribute(:ip, @ip.to_i)
end
def self.for_ip(addr)
where(:ip => IPAddr.new(addr, Socket::AF_INET).to_i)
end
end
我可以做很多很酷的事情
Download.new(:ip => '127.0.0.1').save
Download.for_ip('127.0.0.1').first.ip.to_i # 2130706433
最佳答案
IpAddress.find(2130706433).downloads # SELECT * FROM downloads WHERE ip_address='2130706433'
这完全是一个语义问题,但如果没有IpAddress表(即,如果没有IpAddress表,我们如何在数据库中找到IpAddress对象2130706433),则可能会发生变化,除非您将IpAddress设置为容器而不是特定的单个IpAddress否则,使用类似于
IpAddress(2130706433).downloads
的构造函数实例化新的。否则,尽管如此,我认为没有IpAddress表没有任何问题为什么你需要它是
belongs_to
,而不仅仅是另一个专栏?如果希望以类似的方式访问模型/对象,可以保留它们:
class Download < ActiveRecord::Base
##Whatever Download-model-specific code you have...
def ip_address
#If nil, initialize new object. Return object.
@ip_address ||= IpAddress(ip_address_val)
end
end
class IpAddress
def initialize(address)
@value = address
end
def downloads
Download.where(:ip_address_val => self.value)
end
end
编辑:
你可以按你的要求重写访问器你只需要在你的代码中小心,对你要求的东西要特别。
看这个文件:http://ar.rubyonrails.org/classes/ActiveRecord/Base.html
在“覆盖默认访问器”部分下
基本上,如果确实要重写该值,并且希望访问db值,则使用
read_attribute(attr_name)
,因此代码可能如下所示:class Download < ActiveRecord::Base
##Whatever Download-model-specific code you have...
def ip_address
#If nil, initialize new object. Return object.
@ip_address ||= IpAddress(read_attribute(:ip_address))
end
end
class IpAddress
def initialize(address)
@value = address
end
def downloads
Download.where(:ip_address => self.value)
end
end
如果你不小心的话,你的代码可能会有点混乱。
关于ruby-on-rails - 无额外表的belongs_to关联,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11903989/