我有一个模型,有一个表。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/

10-11 22:06