我有一个名为IP的类,具有:address
属性和两个虚拟属性::start_ip
和:end_ip
class IP < ActiveRecord::Base
# address attribute is saved in database
# start_ip and end_ip are virtual attribute, used in my form
attr_accessor :start_ip, :end_ip
end
我有一个表单可以让我输入一个IP(进入:地址字段)或一系列地址进入我的虚拟属性的字段(:start_ip和:end_ip)。
如果我在:address字段中输入单个IP,那么一切正常。
如果我输入一系列地址(假设它跨越5个地址),那么我想为该范围内的每个地址创建IP记录,并且我认为最好拒绝当前记录,因为它赢了&因为我输入了一个范围,所以在其地址栏中有一个条目。
所以我想我需要一个before_save回调:
before_save :range_given?
def range_given?
create!([@start_ip..@end_ip])
end
但它并不完全正确。
如何告诉rails忘记当前实例化(和验证)的记录,而是创建5条新记录,将每个地址属性设置为该范围内的IP?
答案 0 :(得分:0)
在您create
行动的控制器中,您可以写下这样的内容:
(params[:start_ip]..params[:end_ip]).each do |ip|
IP.create!(address: ip)
end
添加您需要的代码。
PD。也许您应该重新考虑您的域模型,因为IP地址不同于IP范围
答案 1 :(得分:0)
很容易解决这个问题:
def create_from_range
# We are dealing with a range, so lets
# turn both ends into IPAddr objects
# so that we can do some Ruby magic on them
start_addr = IPAddr.new(start_ip)
end_addr = IPAddr.new(end_ip)
# Now that we have the start and end points of
# of our range, we can call "to_a" on it, which
# will give us a list of all the IPs from start to end
range = (start_addr..end_addr).to_a
# We need to shift the first value off the array,
# and assign it's address to the record we are
# currently in the middle of creating, as it does
# not have an address yet
#
# No need to call save on this as we are in a
# before_save filter but you might need to do
# that, depending on your domain
first_ip = range.shift
self.address = first_ip.to_s
# Now we loop through the remaining items in our range
# (array of IPs) and create a new record for each one
range.each{ |ip| IPcreate! address: ip.to_s }
end
容易,没有搞乱。