-
Notifications
You must be signed in to change notification settings - Fork 43
2199 - 3 #277
base: master
Are you sure you want to change the base?
2199 - 3 #277
Changes from 7 commits
864c2e7
2cf4112
8d6ee8d
f9a449e
94cac61
49401ad
8a42710
9490ddc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.env |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
source 'https://rubygems.org' | ||
|
||
gem 'capybara' | ||
gem 'dotenv' | ||
gem 'ohm' | ||
gem 'poltergeist' | ||
gem 'redis' | ||
gem 'shotgun' | ||
gem 'sinatra' | ||
group :development do | ||
gem 'pry' | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
GEM | ||
remote: https://rubygems.org/ | ||
specs: | ||
addressable (2.5.2) | ||
public_suffix (>= 2.0.2, < 4.0) | ||
capybara (3.4.1) | ||
addressable | ||
mini_mime (>= 0.1.3) | ||
nokogiri (~> 1.8) | ||
rack (>= 1.6.0) | ||
rack-test (>= 0.6.3) | ||
xpath (~> 3.1) | ||
cliver (0.3.2) | ||
coderay (1.1.2) | ||
dotenv (2.4.0) | ||
hiredis (0.6.1) | ||
method_source (0.9.0) | ||
mini_mime (1.0.0) | ||
mini_portile2 (2.3.0) | ||
mustermann (1.0.2) | ||
nest (3.1.1) | ||
redic | ||
nokogiri (1.8.4) | ||
mini_portile2 (~> 2.3.0) | ||
ohm (3.1.1) | ||
nest (~> 3) | ||
redic (~> 1.5.0) | ||
stal | ||
poltergeist (1.18.1) | ||
capybara (>= 2.1, < 4) | ||
cliver (~> 0.3.1) | ||
websocket-driver (>= 0.2.0) | ||
pry (0.11.3) | ||
coderay (~> 1.1.0) | ||
method_source (~> 0.9.0) | ||
public_suffix (3.0.2) | ||
rack (2.0.5) | ||
rack-protection (2.0.3) | ||
rack | ||
rack-test (1.1.0) | ||
rack (>= 1.0, < 3) | ||
redic (1.5.0) | ||
hiredis | ||
redis (4.0.1) | ||
shotgun (0.9.2) | ||
rack (>= 1.0) | ||
sinatra (2.0.3) | ||
mustermann (~> 1.0) | ||
rack (~> 2.0) | ||
rack-protection (= 2.0.3) | ||
tilt (~> 2.0) | ||
stal (0.3.0) | ||
redic (~> 1.5) | ||
tilt (2.0.8) | ||
websocket-driver (0.7.0) | ||
websocket-extensions (>= 0.1.0) | ||
websocket-extensions (0.1.3) | ||
xpath (3.1.0) | ||
nokogiri (~> 1.8) | ||
|
||
PLATFORMS | ||
ruby | ||
|
||
DEPENDENCIES | ||
capybara | ||
dotenv | ||
ohm | ||
poltergeist | ||
pry | ||
redis | ||
shotgun | ||
sinatra | ||
|
||
BUNDLED WITH | ||
1.16.1 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
require 'capybara' | ||
require 'capybara/poltergeist' | ||
Capybara.register_driver :poltergeist do |app| | ||
Capybara::Poltergeist::Driver.new(app, js_errors: false) | ||
end | ||
|
||
# Configure Capybara to use Poltergeist as the driver | ||
Capybara.default_driver = :poltergeist |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
require 'dotenv/load' | ||
# analyze comment | ||
class CommentAnalyzer | ||
ACCESS_KEY = ENV['ACCESS_KEY'] | ||
AZURE_ENDPOINT = ENV['AZURE_ENDPOINT'] | ||
|
||
def initialize(texts) | ||
@texts = texts | ||
end | ||
|
||
# :reek:NestedIterators | ||
# rubocop:disable Metrics/AbcSize | ||
def analyze | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Metrics/AbcSize: Assignment Branch Condition size for analyze is too high. [16.03/15] |
||
JSON.parse(run_request.body)['documents'].each_with_object([]) do |result, store| | ||
document = documents.find { |doc| doc[:id].to_s == result['id'] } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NestedIterators: CommentAnalyzer#analyze contains iterators nested 2 deep. More info. |
||
store << { | ||
text: document[:text], | ||
rating: result['score'] * 200 - 100 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The formula is too magical for me (where do the numbers (*200 - 100 ) come from?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We get a decimal number and this formula needed to lead it to necessary range |
||
} | ||
end | ||
end | ||
# rubocop:enable Metrics/AbcSize | ||
|
||
def endpoint | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, what endpoint? I see from the code below that it's the |
||
@endpoint ||= URI(AZURE_ENDPOINT) | ||
end | ||
|
||
# :reek:FeatureEnvy | ||
def request | ||
request = Net::HTTP::Post.new(endpoint) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can use Net::HTTP::Post.new(endpoint).tap do |request|
request['Content-Type'] = 'application/json'
request['Ocp-Apim-Subscription-Key'] = ACCESS_KEY
request.body = serialized_texts
end |
||
request['Content-Type'] = 'application/json' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FeatureEnvy: CommentAnalyzer#request refers to 'request' more than self (maybe move it to another class?). More info. |
||
request['Ocp-Apim-Subscription-Key'] = ACCESS_KEY | ||
request.body = serialized_texts | ||
request | ||
end | ||
|
||
def documents | ||
@documents ||= @texts.map do |text| | ||
{ id: text.object_id, language: 'ru', text: text } | ||
end | ||
end | ||
|
||
def serialized_texts | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it's |
||
{ documents: documents }.to_json | ||
end | ||
|
||
def run_request | ||
https = Net::HTTP.new(endpoint.host, endpoint.port) | ||
https.use_ssl = true | ||
https.request(request) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# parse node and find text and rating | ||
class CommentParser | ||
def initialize(node) | ||
@node = node | ||
end | ||
|
||
def text | ||
@text ||= @node.all('.news-comment__speech > div > p').map(&:text).reduce(&:+) | ||
end | ||
|
||
def rating | ||
@rating ||= @node.all('.like-control span').sum { |mark| mark.text.to_i } | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
require 'pry' | ||
require_relative '../app/comment_parser' | ||
require_relative 'capybara_initializer' | ||
|
||
# class for parsing | ||
class OnlinerPageParser | ||
COMMENTS_TO_TAKE = 50 | ||
|
||
def initialize(link) | ||
@link = link | ||
end | ||
|
||
def browser | ||
@browser ||= Capybara.current_session | ||
end | ||
|
||
# :reek:TooManyStatements | ||
def visit_page | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TooManyStatements: OnlinerPageParser#visit_page has approx 7 statements. More info. |
||
attempts = 0 | ||
begin | ||
browser.visit(@link) | ||
rescue StandardError => exception | ||
attempts += 1 | ||
sleep(2 * attempts) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did you choose There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I use exponential backoff. I did something wrong?? |
||
retry if attempts <= 3 | ||
raise exception | ||
end | ||
end | ||
|
||
def show_all_comments | ||
browser.find('.button-style.button-style_subsidiary.button-style_big.news-form__button'\ | ||
'.news-form__button_width_full.news-form__button_font-weight_semibold').click | ||
sleep(5) | ||
end | ||
|
||
def top_comment_texts | ||
visit_page | ||
show_all_comments | ||
top_comments.map(&:text) | ||
end | ||
|
||
def comment_nodes | ||
browser.all('[id^="comment-"]').drop(1) | ||
end | ||
|
||
def comments | ||
comment_nodes.map { |comment_node| CommentParser.new(comment_node) } | ||
end | ||
|
||
def top_comments | ||
comments.sort_by(&:rating).reverse.first(COMMENTS_TO_TAKE) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
require 'sinatra/base' | ||
require 'ohm' | ||
require_relative 'app/onliner_page_parser' | ||
require_relative 'app/comment_analyzer' | ||
require_relative 'controllers/application_controller' | ||
require_relative 'models/page' | ||
require_relative 'models/comment' | ||
|
||
# Dir.glob('./{helpers, controllers}/*.rb').each { |file| require file } | ||
map('/') { run ApplicationController } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
require 'sinatra' | ||
require 'pry' | ||
# class ApplicationController | ||
class ApplicationController < Sinatra::Base | ||
set views: 'views/' | ||
|
||
get '/' do | ||
redirect '/pages' | ||
end | ||
|
||
get '/pages' do | ||
@pages = Page.all | ||
erb :index | ||
end | ||
|
||
get '/pages/new' do | ||
erb :new | ||
end | ||
|
||
get '/pages/:id' do | ||
@page = Page[params[:id]] | ||
erb :show | ||
end | ||
|
||
post '/pages' do | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's meditate on this endpoint. I'd like to have less code in here. #app.rb
post '/pages' do
if Page.exists?(link: link)
@page = Page.find(link: link)
else
@page = Page.create_from(link: link)
end
erb :show
end It's just an idea, but it will make your post action more verbose and will hide all Page and Comment creation logic. |
||
link = params[:link] | ||
@page = Page.find(link: link).first | ||
unless @page | ||
comment_texts = OnlinerPageParser.new(link).top_comment_texts | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess the Or if you want to stick to comments, call it |
||
comments_with_score = CommentAnalyzer.new(comment_texts).analyze | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Eventually, it's a |
||
@page = Page.create(link: link) | ||
comments_with_score.each do |comment_data| | ||
Comment.create(comment_data.merge(page: @page)) | ||
end | ||
end | ||
erb :show | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Comment model | ||
class Comment < Ohm::Model | ||
attribute :text | ||
attribute :rating | ||
reference :page, 'Page' | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Page model | ||
class Page < Ohm::Model | ||
attribute :link | ||
collection :comments, 'Comment' | ||
index :link | ||
|
||
def rating | ||
comments.sum { |comment| comment.rating.to_f } / comments.count | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<a href="/pages/new">Analyse new link!! </a> | ||
<table class="table table-striped table-hover"> | ||
<thead> | ||
<tr> | ||
<th> Number </th> | ||
<th> Link </th> | ||
<th> Rating </th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<% @pages.each do |page| %> | ||
<tr> | ||
<td><a href="<%= url("/pages/#{page.id}") %>"><%= page.id %></a></td> | ||
<td><a href="<%= page.link %>"><%= page.link %></a></td> | ||
<td><%= page.rating %></td> | ||
</tr> | ||
<% end %> | ||
</tbody> | ||
</tbody> | ||
</table> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<title>Analyzer</title> | ||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" /> | ||
</head> | ||
<body> | ||
<%= yield %> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<form method="post" action=<%= url('/pages') %>> | ||
<label for="link">Link:</label> | ||
<input type="text" name="link"> | ||
<input type="submit"> | ||
</form> | ||
<a href="/">Back to Index</a> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<table> | ||
<tr> | ||
<td><strong>Link:</strong></td> | ||
<td><%= @page.link %></td> | ||
</tr> | ||
<tr> | ||
<td><strong>Average rating:</strong></td> | ||
<td><%= @page.rating.to_i %></td> | ||
</tr> | ||
</table> | ||
|
||
<table class="table table-striped table-hover"> | ||
<thead> | ||
<tr> | ||
<th> Rating </th> | ||
<th> Comment </th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<% @page.comments.each do |comment| %> | ||
<tr> | ||
<td><%= "#{comment.rating.to_i}" %></td> | ||
<td><%= "#{comment.text}" %></td> | ||
</tr> | ||
<% end %> | ||
</tbody> | ||
</table> | ||
|
||
|
||
<a href="/">Back to Index</a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does Azure endpoint contain responsive information?
If no, why should we store it in
.ENV
variable?