Ruby on Rails:为什么这是一个无限循环?

时间:2014-09-11 18:02:27

标签: ruby-on-rails if-statement activerecord

我对Rails / Ruby相当新,所以我现在感觉自己像个白痴。我的程序采用了一系列链接并创建了“列表”。基于这些链接。为了确保重写被覆盖,我使用:

if Listing.find_by_address(address).nil? == true
                listing = Listing.new
                listing.address = address
else
                listing = Listing.find_by_address(address)
end 

这导致无限循环,其中列表表一遍又一遍地检查相同的地址,我似乎无法弄清楚原因。如果有帮助,该表目前是空的。我搜索了SO和谷歌并且无法解决这个问题。我提前道歉,因为他是一个非常随意的人。

有关其他参考:

        links.each do |link|
        mech.get(root + link) 
        if mech.page.search('li:contains("Property Type") span')[1].text != "Land"
            # address is piecemeal on realtor.com, combine pieces to make full address
            address = mech.page.search("#PropertyAddress .blocker").text + " " + mech.page.search("#PropertyAddress .text-base")[0].text + ", " + mech.page.search("#PropertyAddress .text-base")[1].text + " " + mech.page.search("#PropertyAddress .text-base")[2].text
            # check by address if there is already a db entry that matches this address
            # if there isn't an entry make a new listing otherwise update the old one
            if Listing.find_by_address(address).nil?
                listing = Listing.new(address: address)
                listing.save
            else
                listing = Listing.find_by_address(address)
            end 
            listing.price = mech.page.search(".text-condensed span").text.scan(/\d+,\d+/)[0].gsub(',', '').to_i
            # above method looks complex but isn't. 1. Finds the price, scans it for the digits only, 
            # replaces the comma with blank space and converts to integer for the lisitng model (so it can be easily sorted)
            sqftregex = /\d+,\d+\sSq Ft/
            if mech.page.body.scan(/\d+,\d+\sSq Ft/)[0] == nil then
                sqftregex = /\d+\sSq Ft/
            end
            listing.sqft = mech.page.body.scan(sqftregex)[0].gsub(",","").delete(" Sq Ft").to_i
            # same as above, regex looks complicated. scans the page for the sqft, the first item in array
            # is the sq ft. the second item is the lot size for the regex below.
            if mech.page.body.scan(/\d+,\d+\sSq Ft/)[1] != nil then
                listing.lot_size = mech.page.body.scan(/\d+,\d+\sSq Ft/)[1].gsub(",","").delete(" Sq Ft").to_i
            end 
            listing.description = mech.page.search(".property-description").text.gsub("\r", "").gsub("\n", "").strip
            # finds he description and strips it of unwanted characters and whitespace
            listing.year_built = mech.page.search('.list-sidebyside:contains("Year Built")')[0].text.scan(/\d+/)[0].to_i
            listing.bedrooms = mech.page.search('.list-sidebyside:contains("Beds")')[0].text.scan(/\d/)[0].to_i
            listing.bathrooms = mech.page.search('.list-sidebyside:contains("Baths")')[0].text.scan(/\d/)[0].to_i
            listing.list_date = mech.page.search('#OnSite table tr td')[0].text # column needs to be updated to date instead of string
            listing.property_type = mech.page.search('li:contains("Property Type") span')[1].text
            # next step get photos and change list_date from :string to :date
            if mech.page.search('.gallery-img')[0] != nil then
                photo_root = mech.page.search('.gallery-img')[0]['src'].scan(/^.+?-m/) # finds the root of photo urls
                total_photos = mech.page.search('#TabDetails ul li')[1].text.scan(/\d+/)[0].to_i # finds the total number of photos
                listing.photos = []
                total_photos.times do |iter|
                    str = iter
                    str = str.to_s
                    listing.photos << photo_root[0] + str + "r.jpg"
                end
            end
        end 
    end

2 个答案:

答案 0 :(得分:1)

这是因为您没有将记录保存到数据库中,结果再次调用Listing.find_by_address(address)

if Listing.find_by_address(address).nil? # you don't need to add `== true`
  listing = Listing.new(address: address)
  listing.save
else
  listing = Listing.find_by_address(address)
end

答案 1 :(得分:1)

正如Mr.Yoshiji指出,您需要首先保存记录以使用Listing进行验证。您可以将代码更改为:

if listing = Listing.find_by_address(address) # no need to see for `.nil? == true`
  listing = Listing.create(address: address)
else
  listing
end

编辑:您实际上可以使用Rails'find_or_create_by_*方法将上述if-else语句放在一行代码中。

Rails 3.x或更低:

listing = Listing.find_or_create_by_address(address)

Rails 4.x:

listing = Listing.find_or_create_by(address: address)