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>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 3 - 在另一个帖子的SHOW视图中无法创建新帖子