将嵌套资源添加到搜索结果

时间:2018-10-12 02:58:37

标签: ruby-on-rails search nested-resources

我正在创建一个实现以下搜索功能的Rails应用。

application.html.erb

<!doctype html>

<html>

<head>
  <style>
    html,
    body {
      font: 400 16px/1.5 Consolas
    }
    
    fieldset {
      width: fit-content;
      padding: 15px
    }
    
    legend {
      font-size: 1.5rem
    }
    
    button {
      width: 5ch;
      text-align: center
    }
    
    output {
      display: block;
    }
  </style>
</head>

<body>
  <form id="drumMachine">

    <fieldset class='mainControl'>
      <legend>
        <output id="display">&nbsp;</output>
      </legend>

      <fieldset class="controls">

        <button id="bQ" class="drum-pad" data-txt="Heater 1">
    <audio class="clip" id="aQ" src="https://s3.amazonaws.com/freecodecamp/drums/Heater-1.mp3" preload="auto"></audio>Q</button>

        <button id="bW" class="drum-pad" data-txt="Heater 2">
    <audio class="clip" id='aW' src="https://s3.amazonaws.com/freecodecamp/drums/Heater-2.mp3" preload="auto"></audio>W</button>

        <button id="bE" class="drum-pad" data-txt="Heater 3">
    <audio class="clip" id='aE' src="https://s3.amazonaws.com/freecodecamp/drums/Heater-3.mp3" preload="auto"></audio>E</button>
      </fieldset>

      <fieldset class="controls">

        <button id="bA" class="drum-pad" data-txt="Heater 4">
    <audio class="clip" id='aA' src="https://s3.amazonaws.com/freecodecamp/drums/Heater-4_1.mp3" preload="auto"></audio>A</button>

        <button id="bS" class="drum-pad" data-txt="Heater 5">
    <audio class="clip" id='aS'src="https://s3.amazonaws.com/freecodecamp/drums/Heater-6.mp3"></audio>S</button>

        <button id="bD" class="drum-pad" data-txt="Open HH">
    <audio class="clip" id='aD'src="https://s3.amazonaws.com/freecodecamp/drums/Dsc_Oh.mp3"></audio>D</button>

      </fieldset>

      <fieldset class="controls">
        <button id="bZ" class="drum-pad" data-txt="KicknHat">
    <audio class="clip" id='aZ'src="https://s3.amazonaws.com/freecodecamp/drums/Kick_n_Hat.mp3"></audio>Z</button>

        <button id="bX" class="drum-pad" data-txt="Kick">
    <audio class="clip" id='aX'src="https://s3.amazonaws.com/freecodecamp/drums/RP4_KICK_1.mp3"></audio>X</button>

        <button id="bC" class="drum-pad" data-txt="Closed HH">
    <audio class="clip" id='aC' src="https://s3.amazonaws.com/freecodecamp/drums/Cev_H2.mp3"></audio>C</button>

      </fieldset>
    </fieldset>
  </form>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <script>
    // Callback function playMedia() handles both events
    $(document).on('keyup', playMedia);
    $('.drum-pad').on('click', playMedia);


    function playMedia(e) {
      /* 
      Prevent <form> from submitting data to a server when a <button>
      is clicked. This behavior can also be prevented by adding:
      type="button" to each <button> as well.
      */
      e.preventDefault();
      var letter, info;

      //  If the event.type is a click then...
      if (e.type === 'click') {
        // ...get the #id of the clicked node...
        var ID = e.target.id;
        // ...get the text in the clicked node's data-txt attribute
        info = e.target.dataset.txt;
        // Next split the text of the #id and keep the last letter
        letter = ID.split('').pop();
        // But if the event.type is a keyup...
      } else if (e.type === 'keyup') {
        /*
         ...get the keycode and run it through the switch() to
         get the letter associated with a <button>/<audio> pair.
         */
        switch (e.keyCode) {
          case 81:
            letter = "Q";
            break;
          case 87:
            letter = "W";
            break;
          case 69:
            letter = "E";
            break;
          case 65:
            letter = "A";
            break;
          case 83:
            letter = "S";
            break;
          case 68:
            letter = "D";
            break;
          case 90:
            letter = "Z";
            break;
          case 88:
            letter = "X";
            break;
          case 67:
            letter = "C";
            break;
        }
        /*
        Find the correct <button> and extract the text from its
        data-txt attribute
        */
        info = document.getElementById('b' + letter).dataset.txt;
      } else {
        // Otherwise end function
        return false;
      }
      // Find the correct <audio>
      var node = document.getElementById('a' + letter);
      // Play <audio>
      node.play();
      /*
      Set the value of output#display to the extracted text from
      data-txt 
      */
      document.getElementById('display').value = info;
      return false;
    }
  </script>
</body>

</html>

article.rb

<div class="searchbar">
  <%= form_tag(articles_path, :method => "get", id: "search-form") do %>
    <%= text_field_tag :search, params[:search], placeholder: "    Search", :class => "search_form"  %>
    <%= submit_tag "Search", :name => nil %>
  <% end %>
</div>

articles_controller.rb

def self.search(search)
    where("title LIKE ? OR creator LIKE ? OR description LIKE ?", "%#{search}%", "%#{search}%", "%#{search}%") 
end

这使我可以搜索所有主要资源,但搜索结果中不包括嵌套资源。有没有办法将这些资源包含在同一功能中?

1 个答案:

答案 0 :(得分:0)

您需要进行一些连接,并定义一种语法,以将相关的连接信息传递到您的搜索方法中。

这很快就会变得很复杂,我强烈建议您不要重新发明轮子,而是使用现有的解决方案,例如ransack。这会让您做类似的事情

Article.ransack(title_cont: "code", author_name_cont: "bob").result

在此示例中,Author是它自己的模型,与Article关联,并且包含字段name

它还可以很好地与视图和表单配合使用,因此您无需手动将所有内容手动键入正确的关联和字段即可轻松实现搜索表单。

(我个人不喜欢它们的连接语法,但是可以完成工作。)