【问题标题】:Calling a controller action from a rake task从 rake 任务调用控制器动作
【发布时间】:2016-11-01 18:19:02
【问题描述】:

我在应用程序控制器中有以下内容:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  def api_auth
    @api_key = Rails.application.secrets.api_key
    @api_secret = Rails.application.secrets.api_secret
    @host_id = Rails.application.secrets.host_id
    @data_type = 'JSON'

    @options = {
      body: {
        api_key: @api_key,
        api_secret: @api_secret,
        host_id: @host_id,
        data_type: @data_type
      }
    }
  end
end

在我的控制器中,我有...

  before_action :api_auth
  ...
  def get_stuff
response = HTTParty.post("api_url", @options)

stuffs = response.parsed_response["stuffs"]
current_stuffs = stuff.all
stuffs.each do |w|
  #unless stuff id already exists in DB, then create it
  #what about if an attribute of a stuff is updated? How do we capture that? UUID?
  unless (current_stuffs.pluck :stuff_id).map(&:to_s).include?(w["id"].to_s)
     stuff.create(stuff_id: w["id"], topic: w["topic"], start_time: w["start_time"], join_url: w["join_url"])
  end
end

结束

..以及下面的 rake 任务...

desc "Heroku task to get stuff"
task :get_stuff => :environment do
  puts "Getting stuff from api..."
  session = ActionDispatch::Integration::Session.new(Rails.application)
  session.post "/posts/get_stuff"
  puts "done."
end

路线正确,运行任务时我没有收到任何错误。但是,当我运行任务时,我的数据库更新操作没有发生。

我知道该操作有效,因为我在调用相同操作的视图中设置了一个简单的 button_to。

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    你从错误的一端接近它。无需尝试从应用程序中访问 http 端点,只需直接执行该操作中的逻辑即可。

    您已经在应用环境中并且可以访问所有代码!您不需要 http 接口。

    但是,如果您坚持使用 http 接口,则可以像获取外部 api 端点一样执行此操作。以Net::HTTP 为例。

    【讨论】:

    • 我想这是我的问题;我如何调用已经存在的逻辑......在控制器中。我知道逻辑在代码中......在这种情况下是控制器。我可以将逻辑移动到模型并通过类方法从那里调用它,但我认为将逻辑留在控制器中更适合我想做的事情。是否有另一种方法可以调用其他通过 restful 路由运行的控制器?
    • @Lumbee 取决于它是什么样的逻辑。最好将该逻辑移到其他地方(模型或服务对象或类似的东西)
    • 我听到了。我在问题中添加了更多上下文和代码。希望现在更有意义。
    • @Lumbee:是的,这就是我要说的。这种逻辑绝对不属于控制器。它应该被提取到一个专用对象中,该对象查询该 api。控制器应该担心对传入用户进行身份验证、呈现正确的视图等。针对外部 API 进行身份验证并知道如何从中获取数据不是控制器的工作。更不用说知道如何解析响应以及如何处理它了。
    【解决方案2】:

    为了后代,这是我想出的:

    我摆脱了应用控制器中的代码。

    在 stuff.rb 我做了...

    class Stuff < ApplicationRecord
    
      def self.get_stuff       
        options = {
      body: {
        api_key: Rails.application.secrets.zoom_api_key,
        api_secret: Rails.application.secrets.zoom_api_secret,
        host_id: Rails.application.secrets.zoom_host_id,
        data_type: 'JSON'
      }
    }
      end
    
      response = HTTParty.post("api_url", @options)
    
      stuffs = response.parsed_response["stuffs"]
      current_stuffs = stuff.all
      stuffs.each do |w|
    
        unless (current_stuffs.pluck :stuff_id).map(&:to_s).include?(w["id"].to_s)
         stuff.create(stuff_id: w["id"], topic: w["topic"], start_time: w["start_time"], join_url: w["join_url"])
      end
    end
    

    结束

    在控制器中,只需调用 get_stuff 方法...

    def get_stuff
        Stuff.get_stuff
    end
    

    ..以及下面的 rake 任务...

    desc "Heroku task to get stuff"
    task :get_stuff => :environment do
      puts "Getting stuff from api..."
      Stuff.get_stuff
      puts "done."
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-13
      • 2013-09-01
      • 2011-06-17
      • 1970-01-01
      • 1970-01-01
      • 2011-05-23
      相关资源
      最近更新 更多