Save diff on change

webui
aeris 5 years ago
parent 83f1818889
commit f634b1da88
  1. 55
      app/models/site.rb
  2. 28
      app/models/target.rb
  3. 21
      config/initializers/fixture.rb
  4. 1
      db/migrate/20180510000002_create_sites.rb
  5. 62
      db/schema.rb
  6. 20
      spec/models/site_spec.rb

@ -2,6 +2,7 @@ class Site < ApplicationRecord
belongs_to :group, optional: true
belongs_to :template, optional: true
has_many :targets
has_many :diffs
validates :url, presence: true
@ -22,44 +23,46 @@ class Site < ApplicationRecord
targets
end
def diff(context: 3, **kwargs)
reference = self.reference
content = self.content
Diffy::Diff.new reference, content, context: context, **kwargs
end
def content_changed?(reference, content, debug: false)
def diff(reference, content)
targets = self.all_targets
if targets.empty?
if reference != content
puts Utils.diff reference, content if debug
return true
[Diffy::Diff.diff(reference, content)]
else
targets.collect do |target|
diff = target.diff reference, content
next nil unless diff
[target, diff]
end
return false
end
targets.each do |target|
changed = target.content_changed? reference, content, debug: debug
return true if changed
end
false
end.compact
end
def diff!(reference, content, date: Time.now, debug: false)
def diff!(reference, content, date: Time.now)
self.checked_at = date
state = :unchanged
begin
changed = self.content_changed? reference, content, debug: debug
if changed
diffs = self.diff reference, content
unless diffs.empty?
self.reference = content
self.changed_at = self.checked_at
state = :changed
diffs = diffs.collect do |diff|
case diff
when Diffy::Diff
{ diff: diff.dump }
else
target, diff = diff
{
target: target.to_h,
diff: diff.dump
}
end
end
self.diffs.create! content: diffs
end
self.last_error = nil
rescue => e
raise
$stderr.puts e
self.last_error = e
state = :error
@ -69,16 +72,16 @@ class Site < ApplicationRecord
state
end
def check!(debug: false)
def check!
grab = self.grab
content = grab.body
self.update! name: grab.title unless self.name
unless self.reference
self.update! reference: content
return :reference
:reference
else
return self.diff! self.reference, content, debug: debug
self.diff! self.reference, content
end
end
end

@ -14,6 +14,15 @@ class Target < ApplicationRecord
s.join ' '
end
def to_h
{
name: self.name,
from: self.from,
to: self.to,
css: self.css
}.compact
end
def extract_boundary(content)
return nil unless content
if self.from
@ -33,7 +42,7 @@ class Target < ApplicationRecord
return nil
raise "Unable to find `to` #{self.to}"
end
content = content[0..i+self.to.size]
content = content[0..i + self.to.size]
end
content
end
@ -58,22 +67,9 @@ class Target < ApplicationRecord
content
end
def content_changed?(reference, content, debug: false)
reference = self.extract reference
content = self.extract content
changed = reference != content
if changed
puts Utils.diff reference, content if debug
return true
end
false
end
def diff(reference, content, context: 3, **kwargs)
def diff(reference, content)
reference = self.extract reference
content = self.extract content
Diffy::Diff.new reference, content, context: context, **kwargs
Diffy::Diff.diff reference, content
end
end

@ -0,0 +1,21 @@
module Diffy
class Diff
def dump
self.diff
end
def load(diff)
@diff = diff
self
end
def self.dump(diff, options = {})
self.new(nil, nil, options).load diff
end
def self.diff(string1, string2)
return nil if string1 == string2
Diffy::Diff.new string1, string2, context: 3
end
end
end

@ -11,6 +11,7 @@ class CreateSites < ActiveRecord::Migration[5.1]
t.string :last_error
t.datetime :checked_at
t.datetime :changed_at
end
end
end

@ -1,62 +0,0 @@
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2018_05_10_000003) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "groups", force: :cascade do |t|
t.string "name", null: false
t.bigint "template_id"
t.index ["name"], name: "index_groups_on_name", unique: true
t.index ["template_id"], name: "index_groups_on_template_id"
end
create_table "sites", force: :cascade do |t|
t.string "url", null: false
t.string "name"
t.text "reference"
t.bigint "group_id"
t.bigint "template_id"
t.string "last_error"
t.datetime "checked_at"
t.index ["group_id"], name: "index_sites_on_group_id"
t.index ["name"], name: "index_sites_on_name"
t.index ["template_id"], name: "index_sites_on_template_id"
end
create_table "targets", force: :cascade do |t|
t.string "name"
t.string "css"
t.string "from"
t.string "to"
t.bigint "template_id"
t.bigint "group_id"
t.bigint "site_id"
t.index ["group_id"], name: "index_targets_on_group_id"
t.index ["site_id"], name: "index_targets_on_site_id"
t.index ["template_id"], name: "index_targets_on_template_id"
end
create_table "templates", force: :cascade do |t|
t.string "name"
t.index ["name"], name: "index_templates_on_name", unique: true
end
add_foreign_key "groups", "templates"
add_foreign_key "sites", "groups"
add_foreign_key "sites", "templates"
add_foreign_key "targets", "groups"
add_foreign_key "targets", "sites"
add_foreign_key "targets", "templates"
end

@ -24,22 +24,22 @@ RSpec.describe Site, type: :model do
expect(site.changed_at).not_to be_nil
# changes = site._changes
# expect(changes.size).to be 1
# change = changes.first
diffs = site.diffs
expect(diffs.size).to be 1
# diff = diffs.first
#
# expect(change.from).to eq reference
# expect(change.to).to eq content
# expect(diff.from).to eq reference
# expect(diff.to).to eq content
end
def expect_unchanged(content, changed_at = nil)
status = self.check! content
expect(status).to be :unchanged
# expect(site.changed_at).to eq changed_at
#
# changes = site._changes
# expect(changes.size).to be 0
expect(site.changed_at).to eq changed_at
diffs = site.diffs
expect(diffs.size).to be 0
end
def add_target(**args)
@ -52,7 +52,7 @@ RSpec.describe Site, type: :model do
def check!(content)
stub_page content
# site._changes.delete_all
site.diffs.delete_all
site.check!
end

Loading…
Cancel
Save