Test-first-ruby 13_xml_document

时间:2017-04-10 17:38:51

标签: ruby-on-rails ruby rspec

我正在使用test-first-ruby-master(您可以在https://github.com/appacademy/test-first-ruby找到它。)

13_xml_document_spec.rb是我的代码必须通过的Rspec测试。这个测试有几个任务,但它是我的代码没有完成的最后一个(称为"缩进")。

这是Rspec测试:

require "13_xml_document"


describe XmlDocument do
  before do
    @xml = XmlDocument.new
  end

  it "renders an empty tag" do
    expect(@xml.hello).to eq("<hello/>")
  end

  it "renders a tag with attributes" do
    expect(@xml.hello(:name => "dolly")).to eq('<hello name="dolly"/>')
  end

  it "renders a randomly named tag" do
    tag_name = (1..8).map{|i| ("a".."z").to_a[rand(26)]}.join
    expect(@xml.send(tag_name)).to eq("<#{tag_name}/>")
  end

  it "renders block with text inside" do
    expect(@xml.hello { "dolly" }).to eq("<hello>dolly</hello>")
  end

  it "nests one level" do
    expect(@xml.hello { @xml.goodbye }).to eq("<hello><goodbye/></hello>")
  end

  it "nests several levels" do
    xml = XmlDocument.new

    xml_string = xml.hello do
      xml.goodbye do
        xml.come_back do
          xml.ok_fine(:be => "that_way")
        end
      end
    end

    expect(xml_string).to eq('<hello><goodbye><come_back><ok_fine 
be="that_way"/></come_back></goodbye></hello>')
  end

  it "indents" do
    @xml = XmlDocument.new(true)

    xml_string = @xml.hello do
      @xml.goodbye do
        @xml.come_back do
          @xml.ok_fine(:be => "that_way")
        end
      end
    end

    expect(xml_string).to eq(
      "<hello>\n" +
      "  <goodbye>\n" +
      "    <come_back>\n" +
      "      <ok_fine be=\"that_way\"/>\n" +
      "    </come_back>\n" +
      "  </goodbye>\n" +
      "</hello>\n"
    )
  end

end

这是我的代码:

class XmlDocument

def initialize(indentation = false)
    @indentation = indentation
    @counter = 0
end

def method_missing(method, *args, &block) 

    hash = {}

    if block
        if @indentation == false
            "<#{method}>#{yield}</#{method}>"
        elsif @indentation == true

            string = ""

            string << indent1 
            string << "<#{method}>\n"
                (###)
            add_indent

            string << indent1
            string <<  yield + "\n" 

            sub_indent 

            string << indent2
            string << "</#{method}\>"

            string   
        end

    elsif args[0].is_a?(Hash)

        args[0].map { |key,value| "<#{method.to_s} #{key.to_s}=\"#{value.to_s}\"/>" }.join(" ")

    elsif hash.empty?

       "<#{method.to_s}/>"
    end           
end


def indent1
    " " * @counter
end


def indent2
    "  " * @counter
end


def add_indent     
    @counter += 1
end


def sub_indent
    @counter -= 1   
end
end

这是我得到的&#34;缩进&#34;部分:

    <hello>
      <goodbye>
        <come_back>
   +   <ok_fine be="that_way"/>
        </come_back>
      </goodbye>
    </hello>

与正确的答案相反,第4行(&#39; ok_fine是=&#34; that_way&#34; /&#39;)似乎是靠近左边的两个缩进比它应该是的。与其余的线相反,第4行不是块,而是被调用方法的参数&come; back&#39;。 我看不出我的错误在哪里。即使在代码中编写异常(其中(###)在我的代码中)也似乎对第4行没有任何影响。

这是例外(###):

if args[0].is_a?(Hash)
   add_indent
   string << indent
   arg[0].map{|key, value| string << "<#{method.to_s} #{key.to_s}=\"#{value.to_s}\"/>"}
end

注意:我假设如果我设法给第4行提供正确数量的缩进,那么也会增加其后行的缩进次数,因此方法&#39; indent2&#39;需要修改。

1 个答案:

答案 0 :(得分:0)

我弄清楚问题是什么。正如我在我的问题中所说,在Rspec测试中他们有以下输入:

xml_string = xml.hello do
  xml.goodbye do
    xml.come_back do
      xml.ok_fine(:be => "that_way")
    end
  end
end

其中第4行(xml.ok_fine(:be => "that_way"))没有嵌套的块,而是一个参数。在我的代码中,我建立了一个条件(if block),当有一个块存在且在第一个条件内时,第二个条件(if @indentation == true)为@indentation为真时:

 if block
    if @indentation == false
        "<#{method}>#{yield}</#{method}>"
    elsif @indentation == true
            ...

在第二个条件下,我创建了变量'string',我在其中挖掘了不同的部分:

elsif @indentation == true

        string = ""

        string << indent1 
        string << "<#{method}>\n"
            (###)
        add_indent

        string << indent1
        string <<  yield + "\n" 

        sub_indent 

        string << indent2
        string << "</#{method}\>"

        string   
    end

但是因为第4行没有携带块,所以第一个条件(如果是块)不会返回true,因此跳过第4行。

我已经重新编写了代码,所以它现在通过了Rspec测试:

class XmlDocument

def initialize(indentation = false)
    @indentation = indentation
    @counter = 0
end

def method_missing(method, args = nil, &block) 
    string = ""
    arguments = args

    if @indentation == false
        if (arguments == nil) && (block == nil)
            "<#{method.to_s}/>"

        elsif arguments.is_a?(Hash)
            arguments.map { |key,value| "<#{method.to_s} #{key.to_s}=\"#{value.to_s}\"/>" }.join(" ")

        elsif block 
            "<#{method}>#{yield}</#{method}>"
        end

    elsif @indentation == true 

        if (block) || (arguments.is_a?(Hash))

            string << indent1
            string << "<#{method}>\n" unless !block
            add_indent 
            string << indent1 unless !block

            if block
                string <<  yield + "\n" 
            elsif arguments.is_a?(Hash)
                arguments.map { |key,value| string << "<#{method.to_s} #{key.to_s}=\"#{value.to_s}\"/>" }
            end
            sub_indent 
            string << indent2 unless !block
            string << "</#{method}\>" unless !block

            if indent2 == ""
                string << "\n"
            end
        end
        string
    end
end

def indent1
    " " * @counter
end

def indent2
    "  " * @counter
end

def add_indent
    @counter += 1
end

def sub_indent
    @counter -= 1
end

与我在我的问题中写的代码相反,在这一个中,两个主要条件是@indentation == false@indentation == true,在这两个条件中,我为不同的情况建立了不同的例外(块或没有障碍,争论或没有争论......)。特别是对于elsif @indentation == true,我创建了一个接受第4行的条件:if (block) || (arguments.is_a?(Hash)),换句话说,它接受具有块或参数的方法(特别是哈希)。

现在,我在“字符串”中挖出不同的部分,当我到达块时产生分叉:

    if block
       string <<  yield + "\n" 
    elsif arguments.is_a?(Hash)
       arguments.map { |key,value| string << "<#{method.to_s} #{key.to_s}=\"#{value.to_s}\"/>" }

如果有一个块我“屈服”它,如果有和参数是一个哈希我把它铲成'字符串'。

此外,当我缩进或者铲除方法时,存在此异常unless !block,否则它会引入不需要的缩进和'\ n',如果有一个方法没有块(作为行)第4次)。

最后,我必须在最后添加

 if indent2 == ""
    string << "\n"
 end

因为解决方案最后需要'\ n'。

我希望这个答案可以帮助其他人

注意:我在我的问题中写了一个'NOTE',我认为我必须修改'indent2'。那显然我不必这样做,因为我得到的输出没有被认为是第4行(因为它没有块),所以'indent2'的较大缩进(“”)是正确的。