【问题标题】:Rails way to call external API from view?Rails 从视图中调用外部 API 的方式?
【发布时间】:2023-04-02 14:23:01
【问题描述】:

我试图在我的一个视图中包含某种“小部件”,以允许用户使用外部“搜索”API。外部 API 返回一组 JSON 结果。我想使用这个 JSON 向用户显示结果列表。

实现这一点的“rails 方式”是什么?

例如,我想在主页上放置一个搜索输入,并带有一个按钮来搜索外部 API。我创建了一个调用 API 的 PORO,这个 PORO 将返回结果,但是我如何获取用户搜索字符串并将其发布到这个 PORO?

【问题讨论】:

  • 您希望用户如何与小部件进行交互?您愿意在用户提交搜索参数后重新加载整个页面吗?在我看来,小部件是你只用 JS 做的那种事情,直接查询 api 并就地呈现结果,而无需通过 ruby​​。但是,如果您必须在将响应呈现给视图之前用 ruby​​ 解析响应,则必须使用常规请求或 ajax 将搜索参数提交给控制器。
  • 你可以试试form_tag,它不绑定模型。 api.rubyonrails.org/classes/ActionView/Helpers/…
  • HTTParty gem 可能是您的答案。试试这个问题:stackoverflow.com/questions/748614/…
  • Using form_for suggests a form for a specific model which doesn't work in this case. 让您的 PORO 成为一个活跃的模型,form_for 将与它完美配合。
  • @TarynEast 的意思是把你的 PORO 变成一个 ActiveModel。 api.rubyonrails.org/classes/ActiveModel/Model.html / 是的..您仍然需要一个控制器来处理该搜索请求。

标签: ruby-on-rails json api


【解决方案1】:

只是总结一下我们在 cmets 中讨论的内容。完成你想要的最简单的方法是需要一个视图来呈现小部件和一个路由 + 控制器来处理搜索请求。

这都是未经测试的代码,但你可以了解它的要点。

# routes.rb
# this can be named and pointed to anywhere you want.
# It's using get just so you can see the search params in the url, which is preety common for the search feature.
get '/search', to: 'searches#show', as: 'search'

# models/search.rb
# Your PORO
class Search
  attr_reader :results
  def initialize(query)
    # perform request and assign results
    @results = HTTParty.get(url, query: { keyword: query })
  end
end

# controllers/searches_controller.rb
def show
  if params[:query]
    @search = Search.new(params[:query])
  end
end

# views/searches/show.html.erb
<%= form_tag search_path, method: :get do %>
  <%= text_field_tag :query, params[:query] %>
  <%= submit_tag %>
<% end %>

# .... renders contents if they're present.
<%= @search.results if @search %>

你还可以做的就是把 Search 变成一个模型,所以它会继承 Naming 并且你可以把它当作一个常规资源来处理。

# routes.rb
# A singular resource will do.
resource :search, only: [:show]

# models/search.rb
include ActiveModel::Model
attr_reader :results
attr_accessor :query
validates :query, presence: true
def perform
  @results = HTTParty.....
end

# controllers/searches_controller.rb
def show
  if search_params = params[:search] && params[:search][:query]
    @search = Search.new(query: search_params)
    @search.perform if @search.valid?
  else
    @search = Search.new
  end
end

# views/searches/show.html.erb
<%= form_for @search, method: :get do |f| %>
  <%= f.text_field :query %>
  <%= f.submit %>
<% end %>

<%= @search.results %>

现在...您可能希望在任何地方渲染您的小部件,而不仅仅是在 /search 中,因此您可以将表单提取到部分中并在 application.html.erb 中渲染它。

如果您选择 ActiveModel 方法,请不要忘记在呈现表单的每个请求中初始化 @search。您可以为此使用before_action

【讨论】:

  • 试试params[:search] &amp;&amp; params[:search][:query]
  • 像魅力一样工作。谢谢好心的先生!
  • 不客气。正如您所知,#dig 是在 ruby​​ 2.3 中引入的。这是深入了解哈希或数组的一种更简洁的方法。
  • 看来他们已经改变了 ActionController::Parameters,它不再是一个哈希了。因此它不起作用。来源:github.com/rails/rails/issues/23104
  • 我相信你的意思是把请求错误从你的 POGO 传递给控制器​​,对吧?我会设置一个实例变量来保存错误或响应状态,并在执行搜索后在控制器内部检查它。然后你可以用一个新的控制器变量或 flash 消息将它传递给视图。
猜你喜欢
  • 1970-01-01
  • 2018-06-26
  • 2021-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-19
  • 2010-11-20
相关资源
最近更新 更多