如何改进 Ruby on Rails 视图中的代码

Posted

技术标签:

【中文标题】如何改进 Ruby on Rails 视图中的代码【英文标题】:How to improve code in Views on Ruby on Rails 【发布时间】:2016-05-09 12:24:54 【问题描述】:

我在文件视图名称中有代码:_result.html.erb,此文件是从文件 show.html.erb 呈现的,两个文件都在一个文件夹中

File _result.html.erb    
<% if @lesson.answers.at(f.index).is_correct %>
      <% if @lesson.answers.at(f.index).id == answer.id %>
        <li class="text-success">
          <%= f.radio_button :answer_id, answer.id, disabled: true %>
          <%= answer.content %>
        </li>
      <% else %>
        <li>
          <%= f.radio_button :answer_id, answer.id, disabled: true %>
          <%= answer.content %>
        </li>
      <% end %>
    <% else %>
      <% if @lesson.answers.at(f.index).id == answer.id %>
        <li class="text-danger">
          <%= f.radio_button :answer_id, answer.id, disabled: true %>
          <%= answer.content %>
        </li>
      <% else %>
        <li>
          <%= f.radio_button :answer_id, answer.id, disabled: true %>
          <%= answer.content %>
        </li>
      <% end %>
    <% end %>

我想改进文件 _result.html.erb 中的这段代码,使其更短,请帮助我!!!

File show.html
<% provide :title, t("start_lesson") %>
<h1><%= @course.name %></h1>
<h2><%= @course.description %></h2>
<h3><%= t "title_question" %></h3>

<% if @lesson.finished.present? %>
  <h4>
    <%= t "score" %>:
    <%= @lesson.results.is_correct_answers.count %> /
    <%= @lesson.words.count %>
  </h4>
<% end %>

<%= form_for [@course, @lesson] do |f| %>
  <%= f.fields_for :results do |builder| %>
    <ul class="list-unstyled">
      <li>
        <%= "#builder.index + 1." %>
        <%= @words.at(builder.index).content %>
      </li>
      <ul class="list-unstyled">
        <% @words.at(builder.index).answers.each do |answer| %>
          <% if @lesson.finished.nil? %>
            <li>
              <%= answer.content %>
              <%= builder.radio_button :answer_id, answer.id %>
              <%= builder.hidden_field :word_id, value: answer.word.id %>
            </li>
          <% else %>
              <%= render "result", f: builder, answer: answer %>
          <% end %>
        <% end %>
      </ul>
    </ul>
  <% end %>
  <% if @lesson.finished.nil? %>
    <%= f.submit t("submit"), class: "btn btn-primary" %>
  <% end %>
<% end %>

【问题讨论】:

当你说改进代码时,你到底需要什么? _results.html.erb 中,您将整个 &lt;li&gt;...&lt;/li&gt; 块重复四次,即使只有类发生了变化。 小改进:您可以使用&lt;ol&gt;,而不是手动渲染索引 (&lt;%= "#builder.index + 1." %&gt;)。 你能详细说明你的模型之间的关系吗?例如:一门课有很多课,一课有很多答案,一个答案有一个结果?等等,还有什么是@words? 【参考方案1】:

这只是一个代码重写练习,所以这里是:

result.html.erb

<% if @lesson.answers.at(f.index).id == answer.id %>
  <% if @lesson.answers.at(f.index).is_correct %>
    <li class="text-success">
  <% else %>
    <li class="text-danger">
  <% end %>
<% else %>
    <li>
<% end %>
      <%= f.radio_button :answer_id, answer.id, disabled: true %>
      <%= answer.content %>
    </li>

或更短(但更难阅读)的版本:

<li<% if @lesson.answers.at(f.index).id == answer.id %>class="<%= @lesson.answers.at(f.index).is_correct ? "text-success" : "text-danger" %>" <% end%>>
  <%= f.radio_button :answer_id, answer.id, disabled: true %>
  <%= answer.content %>
</li>

在第一个示例中,条件被反转以利用两个内部条件中的 else 条件相同的事实,然后仅使用条件来设置 &lt;li&gt; 节点的样式,因为这是唯一的4 块之间的差异。

第二个例子更进一步,它与元素内联进行条件检查,必要时构建类属性。这更难一目了然,但更紧凑。

show.html

<% provide :title, t("start_lesson") %>
<h1><%= @course.name %></h1>
<h2><%= @course.description %></h2>
<h3><%= t "title_question" %></h3>

<% if @lesson.finished.present? %>
  <h4><%= "#t 'score': #@lesson.results.is_correct_answers.count / #@lesson.words.count %></h4>
<% end %>

<%= form_for [@course, @lesson] do |f| %>
  <%= f.fields_for :results do |builder| %>
    <ul class="list-unstyled">
      <li><%= "#builder.index + 1.#@words.at(builder.index).content" %></li>
      <ul class="list-unstyled">
        <% @words.at(builder.index).answers.each do |answer| %>
          <% if @lesson.finished.nil? %>
            <li>
              <%= answer.content %>
              <%= builder.radio_button :answer_id, answer.id %>
              <%= builder.hidden_field :word_id, value: answer.word.id %>
            </li>
          <% else %>
              <%= render "result", f: builder, answer: answer %>
          <% end %>
        <% end %>
      </ul>
    </ul>
  <% end %>
  <% if @lesson.finished.nil? %>
    <%= f.submit t("submit"), class: "btn btn-primary" %>
  <% end %>
<% end %>

这里的大部分更改只是使用字符串插值来组合字符串元素,否则这些元素是多个 &lt;%= %&gt; 块。

构建答案列表的较大循环部分可能存在一些问题。例如,渲染结果(当课程未完成时)缺少&lt;li&gt;&lt;/li&gt; 元素,因此答案只是作为封闭的&lt;ul&gt; 中的一团文本。为了保留它,以防万一它是故意的,中间的大部分都保留了。

但是,这可能不是您真正想要的,因此此版本修复了该问题并进行了更多重组:

<% provide :title, t("start_lesson") %>
<h1><%= @course.name %></h1>
<h2><%= @course.description %></h2>
<h3><%= t "title_question" %></h3>

<% if @lesson.finished.present? %>
  <h4><%= "#t 'score': #@lesson.results.is_correct_answers.count / #@lesson.words.count %></h4>
<% end %>

<%= form_for [@course, @lesson] do |f| %>
  <%= f.fields_for :results do |builder| %>
    <ul class="list-unstyled">
      <li><%= "#builder.index + 1.#@words.at(builder.index).content" %></li>
      <ul class="list-unstyled">
        <% @words.at(builder.index).answers.each do |answer| %>
          <li>
            <% if @lesson.finished.nil? %>
              <%= answer.content %>
              <%= builder.radio_button :answer_id, answer.id %>
              <%= builder.hidden_field :word_id, value: answer.word.id %>
            <% else %>
              <%= render "result", f: builder, answer: answer %>
            <% end %>
          </li>
        <% end %>
      </ul>
    </ul>
  <% end %>
  <% if @lesson.finished.nil? %>
    <%= f.submit t("submit"), class: "btn btn-primary" %>
  <% end %>
<% end %>

这大约是在不折叠结构或仅删除空格的情况下可以达到的最短时间。每个剩余的元素似乎都有一个目的,并被放置在应有的位置,没有冗余或过度复杂。

【讨论】:

以上是关于如何改进 Ruby on Rails 视图中的代码的主要内容,如果未能解决你的问题,请参考以下文章

Ruby on Rails 6 - 如何根据特定路线建模/隐藏视图?

Ruby on Rails:视图更改后,网站未更新

Ruby On Rails 部分渲染

如何从 Ruby on Rails 中的字符串值创建变量名?

如何根据从下拉列表中选择的 CATEGORY 来控制 NEW/EDIT 视图中的列标题。带有 MYSQL 的 Ruby on Rails

Ruby on Rails 使用视图助手中的变量在视图中动态生成字段名称