将Nokogiri对象传递到ERB页面,然后返回到post



这是在Sinatra。在我的"get"中,我创建了一个实例变量,它是从外部xml文件创建的nokogiri对象。我找到一个动词文件并解析nokogiri对象,以便进行页面布局。在我的post方法中,我需要访问相同的nokogiri对象(我可能多次返回post并可能修改nokogiri对象)。我的方法是在动词页面中设置一个隐藏变量,如下所示:

    <input type="hidden" name="test" value= '<%= @test %>' >

然后在我的帖子中,我从该变量创建了一个nokogiri对象,如下所示:

   @test = Nokogiri::XML(params["test"])

这看起来很笨拙,但我对这方面没有经验。无论如何,一切都很好,除了在某个地方,我在xml中嵌入的引号被弄乱了。例如,我的文件中的node是这样开始的:

<property name="blah" value='{"name:foo"}'> </property>

当我把我的post of params["test"]放进去时,我得到了这个:

<property name="blah" value="{"name:foo"}"> </property>

(单引号变成双引号),最后,在将其转换回nokogiri对象后,使用以下代码:

@test = Nokogiri::XML(params["test"])

我得到这个:

<property name="blah" value="{"/>name:foo"}"&gt; </root>

是否有更好的方法来保留对对象的访问?如果没有,是否有一种方法来保留我嵌入的引号(我认为在erb文件中设置隐藏变量是它被破坏的地方)

总结

  1. 将Nokogiri文档缓存在常量中(例如散列或模块),该常量存在于请求中(在同一服务器运行中;见下文)。
  2. 只发送key到表单中的hash。
  3. 使用该键将文档从常量中取出。

package_32.xml

<packages><kittens in_box="true">32</kittens></packages>

cache_nokodocs.rb

require 'sinatra'
require 'nokogiri'
module NokoDocs
  @docs_by_file = {}
  def self.[](file)
    @docs_by_file[file] ||= Nokogiri::XML(IO.read(file))
  end
end
get "/xml/:doc" do
  @doc = params['doc']
  @xml = NokoDocs[@doc]
  <<-ENDHTML
  The XML starts with '#{@xml.root.name}'
  <form method="post" action="/">
    <input type="hidden" name="xml" value="#{@doc}">
    <button type="submit">Go</button>
  </form>
  ENDHTML
end
post "/" do
  @xml = NokoDocs[params['xml']]
  @xml.to_s
end
使用<<p> /strong>
C:>curl http://localhost:4567/xml/package_32.xml
 The XML starts with 'packages'
 <form method="post" action="/">
   <input type="hidden" name="xml" value="package_32.xml">
   <button type="submit">Go</button>
 </form>
# simulate post that the web browser does from the command line 
C:>curl -d xml="package_32.xml" http://localhost:4567/ 
<?xml version="1.0"?>
<packages>
  <kittens in_box="true">32</kittens>
</packages>

任何用户第一次请求一个特定的XML文件时,它将被加载到哈希中;对该文件的后续请求将直接从哈希中获取它,并预先解析。

小心!

  1. 文档将不会在服务器的多个实例中缓存(例如,如果你在反向代理后面)。它们也不会在服务器重新启动时被缓存。然而,如果这些是磁盘上的静态文件,最坏的情况是特定的服务器会话在缓存它之前只需要重新创建一次Nokogiri文档。

  2. 使用磁盘上的文件名,然后让用户将其发回给您,这可能是一件非常非常危险的事情。相反,您可以在加载文档并使用它时创建一个自定义键或随机键。例如:

    require 'digest'
    module NokoDocs
      @docs_by_file = {}
      def self.from_file(file)
        key = Digest::SHA1( file + rand(100) )
        [
          @docs_by_file[key] ||= Nokogiri::XML(IO.read(file)),
          key
        ]
      end
      def self.from_key(key)
        @docs_by_file[key]
      end
    end
    get "/xml/:doc" do
      @xml, @key = NokoDocs.from_file params['doc']
      ...
      "<input type="hidden" name="key" value="#{@key}">"
      ...
    end
    post "/" do
      @xml = NokoDocs.from_key params['key']
    end
    
  3. 这是一个潜在的内存泄漏。用户请求的每个唯一文档都被解析为一个大的Nokogiri文档,并永久保存(直到重新启动服务器)。您可能想要一个记录最后访问时间的系统,并有一个定时作业,定期清除一段时间未访问的项目。

相关内容

最新更新