Rails 6:通过网络抓取控制器操作创建帖子时如何将用户与创建的帖子相关联

Posted

技术标签:

【中文标题】Rails 6:通过网络抓取控制器操作创建帖子时如何将用户与创建的帖子相关联【英文标题】:Rails 6 : How to associate a user to a created post when post is created through web scraping controller action 【发布时间】:2021-09-23 10:25:18 【问题描述】:

这个问题问起来有点复杂,可能更难理解,所以我会尽力添加上下文来解释我的目标。

我的应用程序允许登录用户在汽车经销商的网站上运行网络抓取功能,并将其库存存储到数据库中。我想将运行抓取功能的 current_user.id 与它创建的帖子相关联。

首先,我生成了一个迁移,通过运行将“车辆”与“用户”关联起来

rails g migration AddUserRefToVehicles user:references

然后,我向 Vehicle 模型添加了一个 belongs_to :user 关联

然后,我更新了 VehiclesController 中的创建操作

VehiclesController 调用“scrape”函数,该函数运行“vehicles_spider.rb”模型并创建帖子并将其保存到数据库中。

vehicles_controller.rb:

    class VehiclesController < ApplicationController
      before_action :authenticate_user!
      before_action :set_vehicle, only: %i[ show edit update destroy ]
    
      ...
      
      #Calls vehicles_spider.rb
      def scrape
        url = 'https://www.example.com/vehicles'
        response = VehiclesSpider.process(url)
        if response[:status] == :completed && response[:error].nil?
          flash.now[:notice] = "Successfully scraped url"
        else
          flash.now[:alert] = response[:error]
        end
      rescue StandardError => e
      flash.now[:alert] = "Error: #e"
      end
    
      def new
        @vehicle = Vehicle.new
      end
    
      def create
                   #This didn't work
        @vehicle = Vehicle.new(vehicle_params.merge(user_id: current_user.id))
      end
    
    
...
    
      private
        # Use callbacks to share common setup or constraints between actions.
        def set_vehicle
          @vehicle = Vehicle.find(params[:id])
        end
    
        # Only allow a list of trusted parameters through.
        def vehicle_params
          params.require(:vehicle).permit(:title, :stock_number, :exterior_color, 
              :interior_color, :transmission, :drivetrain, :price)
        end
    end

vehicle.rb

class Vehicle < ApplicationRecord
    belongs_to :user
end

vehicles_spider.rb

class VehiclesSpider < Kimurai::Base
    
require 'nokogiri'
require 'httparty'
require 'byebug'
require 'watir'
    
  @name = 'vehicles_spider'
  @engine = :mechanize

  def self.process(url)
    @start_urls = [url]
    self.crawl!
  end

  def parse(response, url:, data: )
    url = "https://www.example.com/new-vehicles/"

     ... 

            pagination_vehicle_listings.each do |vehicle_listing|
                vehicle = title: ...
                           price: ...
                           color: ...          
                                      
                // This line is what creates a post and saves the scraped data to my database.
                  Vehicle.where(vehicle).first_or_create

                    ... 
     end

schema.rb

ActiveRecord::Schema.define(version: 2021_07_14_104441) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.string "name"
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

  create_table "vehicles", force: :cascade do |t|
    t.string "title"
    t.string "stock_number"
    t.string "exterior_color"
    t.string "interior_color"
    t.string "transmission"
    t.string "drivetrain"
    t.integer "price"
    t.integer "miles"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.bigint "user_id", null: false
    t.index ["user_id"], name: "index_vehicles_on_user_id"
  end

  add_foreign_key "vehicles", "users"
end

在我将“车辆”与“用户”相关联之前,该程序一直很好地保存帖子,现在抓取的数据拒绝保存。我的预感是“vehicle_spider.rb”模型创建的车辆帖子与登录用户没有关联。

【问题讨论】:

【参考方案1】:

如果我对问题的理解正确,您应该可以在运行scrape 操作时访问current_user 对象。

您可以将该对象传递给VehiclesSpider parse 方法和类似下面的方法以将数据持久保存在数据库中。

current_user.vehicles.where(vehicle).first_or_create ...

【讨论】:

感谢您的建议,但没有奏效。 Vehicles_spider.rb 似乎无权访问 current_user。错误消息:错误:#<0x000055caadf42720> 【参考方案2】:

我找到了解决方案。问题是默认情况下,rails 模型无法访问 current_user 对象。我们可以通过将以下内容添加到应用程序控制器来让模型访问current_user 对象。

application_controller.rb

before_action :set_current_user

    def set_current_user
        Vehicle.current_user = current_user
    end

将此添加到车辆模型中

vehicle.rb

cattr_accessor :current_user

现在我们的模型可以访问 current_user 我从 vehicles_spider.rb

重构了这一行
Vehicle.where(vehicle).first_or_create

Vehicle.where(vehicle.merge(user_id: Vehicle.current_user.id)).first_or_create

现在用户 ID 已保存并与帖子相关联!

【讨论】:

以上是关于Rails 6:通过网络抓取控制器操作创建帖子时如何将用户与创建的帖子相关联的主要内容,如果未能解决你的问题,请参考以下文章

Rails:如何实现帖子查看次数?

在rails中创建像app这样的facebook页面

Rails 3 - 在另一个帖子的SHOW视图中无法创建新帖子

Ruby on Rails - 如何为同一操作添加第二条路线?

如何正确地将参数传递给rails表单

构造一个Rails ActiveRecord where子句