0

モデル内に関数を記述して、サイトをスクレイピングし、特定の属性を別のモデル内に保存しました ( story):

def get_content   

          request = HTTParty.get("#{url}")

          doc = Nokogiri::HTML(request.body)

         doc.css("#{anchor}")["#{range}"].each do |entry|

            story = self.stories.new
            story.title = entry.text
            story.url = entry[:href]
            story.save

        end

これは、Sections 変数のurlanchor、および属性を使用します。range範囲属性は配列の範囲として保存されます-つまり0..2、または11..13-しかし、文字列を変数に変換できないと言われています。range整数と文字列として保存しようとしましたが、どちらも失敗します。

範囲の最初と最後を 2 つの別々の整数としてデータベースに入力して配置できることはわかっています["#{beginrange}".."#{endrange}"]が、これは面倒な方法のようです。

他のアイデアはありますか?よろしくお願いします

4

2 に答える 2

1

rangeうーん、が常に ' 1..2' (' ') のような文字列であることが確実な場合は、次のメソッド<Integer >..<Integer>を使用できます。eval

私の IRB コンソールで:

1.9.3p0 :032 > (eval "1..2").each { |l| puts l }
1
2
 => 1..2 
1.9.3p0 :033 > (eval "1..2").inspect
 => "1..2" 
1.9.3p0 :034 > (eval "1..2").class
 => Range

あなたの場合:

doc.css("#{anchor}")[eval(range)].each do |entry|
  #...
end

でもevalなんか危ない。属性が文字列としての範囲であることが確実な場合range(検証と正規表現が役に立ちます)、evalリスクなしで使用できます。

于 2012-11-22T18:10:33.780 に答える
0

私が間違っていることがいくつかあります。

["#{beginrange}".."#{endrange}"]整数の範囲ではなく、以下をArray[]必要とする文字の範囲を作成します。

beginrange = 1
endrange = 2

["#{beginrange}".."#{endrange}"]
=> ["1".."2"]

[beginrange..endrange]
=> [1..2]

ただし、必要な配列範囲の表現を文字列として保存しています。範囲の文字列表現がある場合、これを使用します。

range_value = '1..2'

[Range.new(*range_value.scan(/\d+/).map(&:to_i))]
=> [1..2]

または、排他的な範囲に遭遇する可能性がある場合:

[Range.new(*range_value.scan(/\d+/).map(&:to_i), range_value['...'])]
=> [1..2]

range_value = '1...2'

[Range.new(*range_value.scan(/\d+/).map(&:to_i), range_value['...'])]
=> [1...2]

Range 文字列表現のソースを信頼できない場合、つまり、値が他の誰かが作成したフォームまたはファイルから来ている場合、これらはすべて有効です。入力値を所有している場合、または便宜上データベースに文字列として保存している場合は、次を使用して範囲を簡単に再作成できますeval

eval('1..2').class
=> Range
eval('1..2')
=> 1..2
eval('1...2')
=> 1...2

evalは、使い方を誤ると危険なので、人々は を恐れています。これは、使用を避けるべきだという意味ではなく、安全なときに使用する必要があります。

正規表現を使用して文字列の形式を確認し、受け入れられない場合は例外を発生させてから続行できます。

raise "Invalid range value received" if (!range_value[/\A\d+\s*\.{2,3}\s*\d+\z/])
[eval(range_value)]
于 2012-11-22T18:37:40.847 に答える