rails 6:当通过web scraping控制器操作创建帖子时,如何将用户与创建的帖子相关联

r55awzrz  于 2021-09-29  发布在  Java
关注(0)|答案(2)|浏览(220)

这个问题问起来有点复杂,可能更难理解,所以我会尽力添加上下文来解释我的目标。
我的应用程序允许登录用户在汽车经销商的网站上运行网络抓取功能,并将其库存存储到数据库中。我想将运行刮削功能的用户的当前_user.id与它创建的帖子相关联。
首先,我生成了一个迁移,通过运行 rails g migration AddUserRefToVehicles user:references 然后,我在车辆模型中添加了一个用户关联
然后,我更新了vehiclescontroller中的创建操作
VehicleController调用一个“scrape”函数,该函数运行“vehicles_spider.rb”模型,创建帖子并将其保存到数据库中。
车辆_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

车辆_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”模型arn创建的车辆帖子与登录用户没有关联。

htrmnn0y

htrmnn0y1#

如果我理解正确,您应该可以访问 current_user 在运行 scrape 行动。
您可以将该对象传递给 VehiclesSpider parse方法和类似下面的方法将数据持久化到数据库中。

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

jslywgbw2#

我找到了解决办法。问题是rails模型无法访问 current_user 对象默认情况下。我们可以让模型访问 current_user 对象,将以下内容添加到应用程序控制器。
应用程序\u 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已保存并与帖子关联!

相关问题