如何将来自外部API的数据从视图传递到控制器?

时间:2018-10-14 16:57:51

标签: ruby-on-rails

所以我想将数据从外部api渲染的视图传递到控制器,以便将ID保存到模型/数据库表中。

这是我的观点:

<h1>Heroes</h1>
<% @response.each do |hero| %>
  <div class = "hero_wrap">
    <div class = "img">
      <img src="https://api.opendota.com<%= hero["img"]%>", id ="hero_img"/>
    </div>
    <div class = "fave_container">
    <%= link_to(image_tag('fave.png', class: "fave_img"), new_hero_path) %>
    <%= hero["id"]%>
  </div>
    <div class = "hero_name">
      <%= hero["localized_name"] %>
    </div>
  </div>
<% end %>

我的控制器:

# heroes_controller

class HeroesController < ApplicationController
  def index
    @response = HTTParty.get("https://api.opendota.com/api/heroStats")
  end

  def create
    @hero= Hero.new(params[:id])

    @hero.save
    redirect_to @hero
  end
end

路线:

Rails.application.routes.draw do

  get '/signup', to: 'users#new' 
  get  'pages/home'

  resources :pro_players
  devise_for :users
  resources :heroes
  resources :users

  root 'pages#home'
end

我的英雄模型还不包含任何内容,我只想选择一个英雄ID并将其保存到我的数据库中。

this is my web app

点击带有链接的星标图标时,

服务器日志:

Started GET "/heros?custom_hero_id=1&method=post" for 127.0.0.1 at 
2018-10-15 09:20:53 +0800
Processing by HerosController#index as HTML
  Parameters: {"custom_hero_id"=>"1", "method"=>"post"}
  User Load (0.7ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳/home/don/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord- 
5.2.1/lib/active_record/log_subscriber.rb:98
  Rendering heros/index.html.erb within layouts/application
  Rendered heros/index.html.erb within layouts/application (42.2ms)
  Rendered layouts/_header.html.erb (1.1ms)
  Rendered layouts/_footer.html.erb (0.4ms)
    Completed 200 OK in 770ms (Views: 83.3ms | ActiveRecord: 0.7ms)

更新的日志:

Started POST "/heros?custom_hero_id=21" for 127.0.0.1 at 2018-10-15 10:13:17 +0800
Processing by HerosController#create as HTML
  Parameters: {"authenticity_token"=>"PHDEXdDmPhPX+VdloU2y6yONY5HN5wI2lIfOaSbSKj9+RvTO5Ua3QPuTcreLZtGNDFPaSOXhDVyve6J69+1CQQ==", "custom_hero_id"=>"21"}
  User Load (0.7ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 1], ["LIMIT", 1]]
      ↳/home/don/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
   (0.2ms)  BEGIN
  ↳ app/controllers/heros_controller.rb:9
      Hero Create (0.4ms)  INSERT INTO "heros" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id"  [["created_at", "2018-10-15 02:13:17.032248"], ["updated_at", "2018-10-15 02:13:17.032248"]]
      ↳ app/controllers/heros_controller.rb:9
   (42.3ms)  COMMIT
      ↳ app/controllers/heros_controller.rb:9
 Redirected to http://localhost:3000/heros/10
Completed 302 Found in 59ms (ActiveRecord: 46.9ms)


Started GET "/heros/10" for 127.0.0.1 at 2018-10-15 10:13:17 +0800

AbstractController::ActionNotFound (The action 'show' could not be found for HerosController):

2 个答案:

答案 0 :(得分:0)

您要存储英雄ID还是名字?

我建议您在英雄模型中创建一个方法。像

// heroe.rb

def save_api_heroes_to_db(response)
  response.each do |hero|
    unless hero[:localized_name].exists?
      hero.create(id: hero[:id], name: hero[:localized_name], image: hero[:img])
    end
  end
end

此方法会将英雄ID,名称和图像保存在您的数据库中(除非已经存在)。

您只需要在英雄控制器中的index方法中调用它即可。

希望有帮助。

答案 1 :(得分:0)

默认情况下,:id属性是数据类型为integer 自动递增 属性,该属性在每次使用时都会设置其值将创建模型的新实例。有几种方法可以覆盖其行为或显式设置其值,但是考虑到您是该技术的新手,我不推荐。相反,我建议使用另一个属性存储hero["id"]

的简单解决方案

步骤:

1)生成迁移以在custom_hero_id表中创建新列(例如heroes

rails g migration add_custom_hero_id_to_heroes custom_hero_id:integer

然后执行rake db:migrate

2)更改

<%= link_to(image_tag('fave.png', class: "fave_img"), new_hero_path) %>

<%= link_to(image_tag('fave.png', class: "fave_img"), heroes_path(custom_hero_id: hero["id"]), method: :post) %>

3)最后,将您的create动作更改为以下

def create
  @hero= Hero.create(custom_hero_id: params[:custom_hero_id])
  redirect_to @hero
end

更新

由于未知原因,custom_hero_id未保存到数据库。可能是由于禁忌属性错误。尝试将其更改为

def create
  @hero = Hero.new(hero_params)

  if @hero.save
    redirect_to @hero
  end
end

private
def hero_params
  params.permit(:custom_hero_id)
end