Skip to content

Commit 532cb8e

Browse files
authored
Merge pull request #58 from suho/release/0.5.0
2 parents 8b05321 + d46bf81 commit 532cb8e

36 files changed

+1460
-4
lines changed

.rubocop.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
require:
1+
require:
22
- rubocop-rails
33
- rubocop-rspec
44
- rubocop-performance
@@ -44,3 +44,6 @@ RSpec/ContextWording:
4444
Prefixes:
4545
- when
4646
- given
47+
48+
RSpec/NestedGroups:
49+
Max: 5

Gemfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ gem 'sidekiq' # background processing for Ruby
1414
gem 'bootsnap', require: false # Reduces boot times through caching; required in config/boot.rb
1515
gem 'i18n-js', '3.5.1' # A library to provide the I18n translations on the Javascript
1616
gem 'httparty' # A library to call external API
17+
gem 'jsonapi-serializer' #A fast JSON: API serializer for Ruby
1718

1819
# Authentications & Authorizations
1920
gem 'devise' # Authentication solution for Rails with Warden
2021
gem 'pundit' # Minimal authorization through OO design and pure Ruby classes
22+
gem 'doorkeeper' # An OAuth 2 provider.
2123

2224
# Assets
2325
gem 'webpacker', '~>5.2.0' # Transpile app-like JavaScript

Gemfile.lock

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ GEM
163163
discard (1.2.0)
164164
activerecord (>= 4.2, < 7)
165165
docile (1.4.0)
166+
doorkeeper (5.5.4)
167+
railties (>= 5)
166168
erubi (1.10.0)
167169
erubis (2.7.0)
168170
fabrication (2.22.0)
@@ -211,6 +213,8 @@ GEM
211213
json_matchers (0.11.1)
212214
json_schema
213215
json_schema (0.21.0)
216+
jsonapi-serializer (2.2.0)
217+
activesupport (>= 4.2)
214218
kramdown (2.3.1)
215219
rexml
216220
kramdown-parser-gfm (1.1.0)
@@ -505,13 +509,15 @@ DEPENDENCIES
505509
database_cleaner
506510
devise
507511
discard
512+
doorkeeper
508513
fabrication
509514
ffaker
510515
figaro
511516
foreman
512517
httparty
513518
i18n-js (= 3.5.1)
514519
json_matchers
520+
jsonapi-serializer
515521
letter_opener
516522
listen (= 3.1.5)
517523
mini_magick

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
This is a web application that will extract large amounts of data from the Google search results page.
66

7+
## Applications
8+
9+
- Staging: [https://google-search-suv-staging.herokuapp.com/](https://google-search-suv-staging.herokuapp.com/)
10+
- Production: [https://google-search-suv.herokuapp.com/](https://google-search-suv.herokuapp.com/)
11+
712
## Project Setup
813

914
### Prerequisites
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# frozen_string_literal: true
2+
3+
module API
4+
module V1
5+
class ApplicationController < ActionController::API
6+
include API::V1::DoorkeeperAuthentication
7+
rescue_from ActiveRecord::RecordNotFound, Pagy::OverflowError, with: :show_not_found_error
8+
9+
private
10+
11+
def show_not_found_error
12+
render status: :not_found
13+
end
14+
end
15+
end
16+
end
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# frozen_string_literal: true
2+
3+
module API
4+
module V1
5+
class KeywordsController < ApplicationController
6+
include Pagy::Backend
7+
8+
before_action :set_keyword, only: :show
9+
10+
def index
11+
keywords_query.call
12+
pagy, keywords = pagy_array(keywords_query.keywords, pagination_params)
13+
14+
render json: KeywordSerializer.new(keywords, meta: meta_from_pagy(pagy))
15+
end
16+
17+
def create
18+
if save_keywords
19+
SearchKeywordsJob.perform_later(keywords_form.keyword_ids)
20+
21+
render status: :created
22+
else
23+
render_error(
24+
detail: keywords_form.errors.full_messages.first,
25+
code: :invalid_file,
26+
status: :unprocessable_entity
27+
)
28+
end
29+
end
30+
31+
def show
32+
render json: KeywordSerializer.new(@keyword, include: [:links], params: { show_detail: true })
33+
end
34+
35+
private
36+
37+
def save_keywords
38+
keywords_form.save(params[:keywords_file])
39+
end
40+
41+
def keywords_form
42+
@keywords_form ||= KeywordsForm.new(current_user)
43+
end
44+
45+
def keywords_query
46+
@keywords_query ||= KeywordsQuery.new(current_user.keywords, permitted_params)
47+
end
48+
49+
def set_keyword
50+
@keyword = current_user.keywords.find(params[:id])
51+
end
52+
53+
def permitted_params
54+
params.permit(:keyword)
55+
end
56+
57+
def pagination_params
58+
{
59+
page: params.dig(:page, :number) || Pagy::DEFAULT[:page],
60+
items: params.dig(:page, :size)
61+
}
62+
end
63+
64+
def meta_from_pagy(pagy)
65+
{
66+
page: pagy.page,
67+
pages: pagy.pages,
68+
page_size: pagy.items,
69+
records: pagy.count
70+
}
71+
end
72+
end
73+
end
74+
end
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# frozen_string_literal: true
2+
3+
module API
4+
module V1
5+
class PasswordsController < Devise::PasswordsController
6+
include API::V1::OauthApplicationProtection
7+
8+
def create
9+
super do |user|
10+
if user.valid?
11+
render json: {
12+
meta: { message: t('devise.passwords.send_paranoid_instructions') }
13+
}
14+
else
15+
render_error(detail: user.errors.full_messages_for(:email).first)
16+
end
17+
18+
return
19+
end
20+
end
21+
end
22+
end
23+
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# frozen_string_literal: true
2+
3+
module API
4+
module V1
5+
class RegistrationsController < Devise::RegistrationsController
6+
include API::V1::OauthApplicationProtection
7+
8+
def create
9+
super do |user|
10+
if user.persisted?
11+
head :created
12+
else
13+
render_error(detail: user.errors.full_messages.to_sentence)
14+
end
15+
return
16+
end
17+
end
18+
end
19+
end
20+
end
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# frozen_string_literal: true
2+
3+
module API
4+
module V1
5+
class TokensController < Doorkeeper::TokensController
6+
include API::V1::ErrorHandler
7+
8+
private
9+
10+
def revocation_error_response
11+
{
12+
errors: build_errors(
13+
detail: I18n.t('doorkeeper.errors.messages.revoke.unauthorized'),
14+
code: :unauthorized_client
15+
)
16+
}
17+
end
18+
end
19+
end
20+
end

app/controllers/concerns/.keep

Whitespace-only changes.

0 commit comments

Comments
 (0)