Html 使用搜索结果中的Ruby on Rails显示列表/或表

Html 使用搜索结果中的Ruby on Rails显示列表/或表,html,ruby-on-rails,ruby,Html,Ruby On Rails,Ruby,RubyonRails的新特性。提交搜索参数后,我想更新new.html.erb视图以显示album_controller.rb中的搜索结果。我可以创建一个隐藏元素,然后从控制器中显示它吗?搜索结果是字符串数组的数组 我的目标是显示可供选择的相册列表(从HTTPGET请求获得),然后让用户选择要进行的搜索结果 new.html.erb <h4>Search for Album</h4> <%= form_with(url: "/albums/search", me

RubyonRails的新特性。提交搜索参数后,我想更新new.html.erb视图以显示album_controller.rb中的搜索结果。我可以创建一个隐藏元素,然后从控制器中显示它吗?搜索结果是字符串数组的数组

我的目标是显示可供选择的相册列表(从HTTPGET请求获得),然后让用户选择要进行的搜索结果

new.html.erb

<h4>Search for Album</h4>

<%= form_with(url: "/albums/search", method: "get") do %>
  <%= label_tag(:q, "Search for: ") %>
  <%= text_field_tag(:q) %>
  <%= submit_tag("Search") %>
<% end %>

在Rails中,您希望构建包含最少代码的瘦控制器,并且唯一的公共方法应该是与路由对应的操作。这是因为众所周知,控制器很难测试,而且膨胀很快就会成为一个问题

HTTP调用、批处理和其他此类任务不属于控制器。尤其是当它们触及应用程序边界时。相反,您希望创建一个处理HTTP调用的客户机对象,以及封装数据并为应用程序规范化数据的模型

因此,让我们从HTTP调用开始:

# app/clients/audio_scobbler_client.rb
class AudioScrobblerClient
  include Httparty
  format :json
  base_uri "http://ws.audioscrobbler.com/2.0/"

  def initialize(api_key:)
    @base_opts = {
      api_key: api_key,
      format: "json" # may be redundant
    }
  end

  def album_search(query, limit: 15)
    self.class.get(
      @base_opts.reverse_merge(
        method: 'album.search',
        limit: limit
      )
    )
  end
end
这为您提供了一个可以与控制器分开测试的对象,并消除了使用字符串连接构造查询字符串的混乱(永远不要这样做)。它通过执行HTTP请求返回JSON,仅此而已

然后创建一个表示应用程序中搜索结果的模型。记住,持久性不是MVC中模型的唯一角色

# app/models/album.rb
class Album
  include ActiveModel::Model
  include ActiveModel::Attributes
  attr :artist, String
  attr :name, String
  attr :image, String
end
现在,让我们在混合中再抛出一个对象—一个执行API调用并规范化值的服务对象:

# app/services/audio_scrobbler_search.rb
class AudioScrobblerSearch
  def perform(query, **options)
    api_key = ENV["AUDIOSCROBBER_API_KEY"] # or use the encrypted secrets.
    json = AudioScrobblerClient.new(api_key: api_key).album_search(query, options)
    json.dig("results", "albummatches", "album").map do |result|
      # I have no idea what api response looks 
      # like but I have no doubt that you can figure this part out
      Album.new(
         artist: result["name"],
         name: result["name"],
         image: result["image"]
      )
    end
  end
end
然后让我们消除控制器中的所有膨胀:

class AlbumsController < ApplicationController
  # you don't really need the new action at all since a search form can just loop back on itself
  # GET /albums/search?q=believe
  def search
    @search_query = params[:q]
    if @search_query
      @albums = AudioScrobblerSearch.perform(query)
    end
  end
end
class AlbumsController
并在视图中列出相册:

<h4>Search for Album</h4>

<%= form_with(url: "/albums/search", method: "get") do %>
  <%= f.label(:q, "Search for: ") %>
  <%= f.text_field(:q, value: @search_query) %>
  <%= f.submit("Search") %>
<% end %>

<% if @albums %>
  <table>
    <thead>
      <tr>
        <th>Image</th>
        <th>Artist</th>
        <th>Name</th>
      </tr>
    </thead>
    <tbody>
      <% @albums.each do |album| %>
        <tr>
          <td><%= tag.img src: album.image, alt: "Cover art for #{album.name}" %></td>
          <td><%= album.artist %></td>
          <td><%= album.name %></td>
        </tr>
      <% end %>
    </tbody>
  </table>
<% elsif @search_query.present? %>
  <p>No results to display :(</p>
<% end %>
搜索相册
形象
艺术家
名称
没有要显示的结果:(


如果您想在查询中提交一个特定于某个相册的搜索。为什么不这样做:
album.where(title:“inquery\u data”)
尚未创建相册obj。我想显示一个可能的相册列表以供选择(从http get请求获得),然后让用户选择要进行的搜索结果。我不太了解这里的流程。你想给他们一个相册列表,让他们从中选择,然后搜索相册选择导致的内容吗?似乎有点过于复杂。抱歉,如果我不明确,第一次发布。我想在数据库。流程如下:搜索唱片集(通过音乐api),http get请求返回json,将json解析为15个搜索结果,向用户显示搜索结果(我现在遇到了问题),然后最后让用户选择要添加到数据库的搜索结果。在将json放入视图时遇到问题吗?请注意,这个答案只是为了概述一般方法,我实际上根本没有测试api调用。您需要一些程序集,它很可能包含多个错误。谢谢您或者详细的答案,我现在正在看。我有一个问题。在audio_scrobbler_client中,“self.get”的目的是什么。我在这一点上得到了一个命名错误。同样在视图中,我看到您在@albums中迭代。但我不确定如何创建专辑列表。在audio_scrobbler_search.rb中,是否有Album.new()创建一个新的album对象并将其附加到列表中?否-
album。新建(…)
只创建album的一个实例。查看它上面的行
json.dig(“结果”、“albummatches”、“album”)
获取键
obj[“结果”][“albummatches”][“album”]
。遍历数组并返回一个包含块返回值的新数组。
for循环除ruby初学者外,任何人都不使用。很抱歉,它应该是
self.class.get
调用
HTTParty.get
class AlbumsController < ApplicationController
  # you don't really need the new action at all since a search form can just loop back on itself
  # GET /albums/search?q=believe
  def search
    @search_query = params[:q]
    if @search_query
      @albums = AudioScrobblerSearch.perform(query)
    end
  end
end
<h4>Search for Album</h4>

<%= form_with(url: "/albums/search", method: "get") do %>
  <%= f.label(:q, "Search for: ") %>
  <%= f.text_field(:q, value: @search_query) %>
  <%= f.submit("Search") %>
<% end %>

<% if @albums %>
  <table>
    <thead>
      <tr>
        <th>Image</th>
        <th>Artist</th>
        <th>Name</th>
      </tr>
    </thead>
    <tbody>
      <% @albums.each do |album| %>
        <tr>
          <td><%= tag.img src: album.image, alt: "Cover art for #{album.name}" %></td>
          <td><%= album.artist %></td>
          <td><%= album.name %></td>
        </tr>
      <% end %>
    </tbody>
  </table>
<% elsif @search_query.present? %>
  <p>No results to display :(</p>
<% end %>