Merge branch 'main' into awakening

This commit is contained in:
Justin Edmund 2022-12-23 16:36:50 -08:00
commit 7bdee95c0e
109 changed files with 1959 additions and 1784 deletions

18
Gemfile
View file

@ -1,10 +1,10 @@
source 'https://rubygems.org' source 'https://rubygems.org'
ruby '3.0.0' ruby '3.0.0'
gem 'rails'
gem 'pg'
gem 'bootsnap' gem 'bootsnap'
gem 'pg'
gem 'rack-cors' gem 'rack-cors'
gem 'rails'
# A Ruby Web Server Built For Concurrency # A Ruby Web Server Built For Concurrency
gem 'puma' gem 'puma'
@ -16,8 +16,8 @@ gem 'bcrypt'
# Doorkeeper is an OAuth 2 provider for Rails and Grape. # Doorkeeper is an OAuth 2 provider for Rails and Grape.
gem 'doorkeeper' gem 'doorkeeper'
# Templating system with JSON, XML and Plist support. # Simple, Fast, and Declarative Serialization Library for Ruby
gem 'rabl' gem 'blueprinter'
# Optimized JSON. # Optimized JSON.
gem 'oj' gem 'oj'
@ -35,7 +35,7 @@ gem 'gemoji-parser'
gem 'awesome_nested_set' gem 'awesome_nested_set'
# An email validator for Rails # An email validator for Rails
gem "email_validator" gem 'email_validator'
# pg_search builds ActiveRecord named scopes that take advantage of PostgreSQLs full text search # pg_search builds ActiveRecord named scopes that take advantage of PostgreSQLs full text search
gem 'pg_search' gem 'pg_search'
@ -44,8 +44,8 @@ gem 'pg_search'
gem 'will_paginate', '~> 3.3' gem 'will_paginate', '~> 3.3'
group :doc do group :doc do
gem 'sdoc'
gem 'apipie-rails' gem 'apipie-rails'
gem 'sdoc'
end end
group :development, :test do group :development, :test do
@ -53,16 +53,16 @@ group :development, :test do
gem 'dotenv-rails' gem 'dotenv-rails'
gem 'factory_bot_rails' gem 'factory_bot_rails'
gem 'faker' gem 'faker'
gem 'rspec-rails'
gem 'rspec_junit_formatter' gem 'rspec_junit_formatter'
gem 'rspec-rails'
end end
group :development do group :development do
gem 'listen' gem 'listen'
gem 'rubocop' gem 'rubocop'
gem 'solargraph' gem 'solargraph'
gem 'spring-commands-rspec'
gem 'spring' gem 'spring'
gem 'spring-commands-rspec'
end end
group :test do group :test do
@ -70,5 +70,5 @@ group :test do
gem 'byebug' gem 'byebug'
gem 'database_cleaner' gem 'database_cleaner'
gem 'shoulda-matchers' gem 'shoulda-matchers'
gem 'simplecov', :require => false gem 'simplecov', require: false
end end

View file

@ -73,6 +73,7 @@ GEM
backport (1.2.0) backport (1.2.0)
bcrypt (3.1.16) bcrypt (3.1.16)
benchmark (0.2.0) benchmark (0.2.0)
blueprinter (0.25.3)
bootsnap (1.9.1) bootsnap (1.9.1)
msgpack (~> 1.0) msgpack (~> 1.0)
builder (3.2.4) builder (3.2.4)
@ -147,8 +148,6 @@ GEM
activesupport (>= 5.2) activesupport (>= 5.2)
puma (5.5.2) puma (5.5.2)
nio4r (~> 2.0) nio4r (~> 2.0)
rabl (0.14.5)
activesupport (>= 2.3.14)
racc (1.6.0) racc (1.6.0)
rack (2.2.3) rack (2.2.3)
rack-cors (1.1.1) rack-cors (1.1.1)
@ -286,6 +285,7 @@ DEPENDENCIES
awesome_nested_set awesome_nested_set
awesome_print awesome_print
bcrypt bcrypt
blueprinter
bootsnap bootsnap
byebug byebug
database_cleaner database_cleaner
@ -301,7 +301,6 @@ DEPENDENCIES
pg pg
pg_search pg_search
puma puma
rabl
rack-cors rack-cors
rails rails
responders responders

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
module Api
module V1
class ApiBlueprint < Blueprinter::Base
identifier :id
cattr_accessor :current_user
cattr_writer :current_user
end
end
end

View file

@ -0,0 +1,68 @@
# frozen_string_literal: true
module Api
module V1
class CharacterBlueprint < ApiBlueprint
field :name do |w|
{
en: w.name_en,
ja: w.name_jp
}
end
fields :granblue_id, :character_id, :rarity,
:element, :gender, :special
field :uncap do |w|
{
flb: w.flb,
ulb: w.ulb
}
end
field :hp do |w|
{
min_hp: w.min_hp,
max_hp: w.max_hp,
max_hp_flb: w.max_hp_flb
}
end
field :atk do |w|
{
min_atk: w.min_atk,
max_atk: w.max_atk,
max_atk_flb: w.max_atk_flb
}
end
field :race do |w|
[
w.race1,
w.race2
]
end
field :proficiency do |w|
[
w.proficiency1,
w.proficiency2
]
end
field :data do |w|
{
base_da: w.base_da,
base_ta: w.base_ta
}
end
field :ougi_ratio do |w|
{
ougi_ratio: w.ougi_ratio,
ougi_ratio_flb: w.ougi_ratio_flb
}
end
end
end
end

View file

@ -0,0 +1,31 @@
# frozen_string_literal: true
module Api
module V1
class ConflictBlueprint < Blueprinter::Base
field :position, if: ->(_fn, _obj, options) { options.key?(:incoming_position) } do |_, options|
options[:incoming_position]
end
view :characters do
field :conflicts, if: ->(_fn, _obj, options) { options.key?(:conflict_characters) } do |_, options|
GridCharacterBlueprint.render_as_hash(options[:conflict_characters], view: :nested)
end
field :incoming, if: ->(_fn, _obj, options) { options.key?(:incoming_character) } do |_, options|
CharacterBlueprint.render_as_hash(options[:incoming_character])
end
end
view :weapons do
field :conflicts, if: ->(_fn, _obj, options) { options.key?(:conflict_weapons) } do |_, options|
GridWeaponBlueprint.render_as_hash(options[:conflict_weapons], view: :nested)
end
field :incoming, if: ->(_fn, _obj, options) { options.key?(:incoming_weapon) } do |_, options|
WeaponBlueprint.render_as_hash(options[:incoming_weapon])
end
end
end
end
end

View file

@ -0,0 +1,15 @@
# frozen_string_literal: true
module Api
module V1
class EmptyBlueprint < Blueprinter::Base
field :available, if: ->(_field_name, _empty, options) { options.key?(:availability) } do |_, options|
if options.key?(:email)
User.where('email = ?', options[:email]).count.zero?
elsif options.key?(:username)
User.where('username = ?', options[:username]).count.zero?
end
end
end
end
end

View file

@ -0,0 +1,19 @@
# frozen_string_literal: true
module Api
module V1
class ErrorBlueprint < Blueprinter::Base
field :error, if: ->(_field_name, _error, options) { options.key?(:error) } do |_, options|
options[:error]
end
field :errors, if: ->(_field_name, _error, options) { options.key?(:errors) } do |_, options|
options[:errors]
end
field :errors, if: ->(_field_name, _error, options) { options.key?(:exception) } do |_, options|
options[:exception]
end
end
end
end

View file

@ -0,0 +1,25 @@
# frozen_string_literal: true
module Api
module V1
class FavoriteBlueprint < ApiBlueprint
association :user,
name: :user,
blueprint: UserBlueprint,
view: :minimal
association :party,
name: :party,
blueprint: PartyBlueprint,
view: :preview
fields :created_at, :updated_at
view :destroyed do
field :destroyed do
true
end
end
end
end
end

View file

@ -0,0 +1,22 @@
# frozen_string_literal: true
module Api
module V1
class GridCharacterBlueprint < ApiBlueprint
view :uncap do
association :party, blueprint: PartyBlueprint, view: :minimal
fields :position, :uncap_level
end
view :nested do
fields :position, :uncap_level, :perpetuity
association :character, name: :object, blueprint: CharacterBlueprint
end
view :full do
include_view :nested
association :party, blueprint: PartyBlueprint, view: :minimal
end
end
end
end

View file

@ -0,0 +1,22 @@
# frozen_string_literal: true
module Api
module V1
class GridSummonBlueprint < ApiBlueprint
view :uncap do
association :party, blueprint: PartyBlueprint, view: :minimal
fields :position, :uncap_level
end
view :nested do
fields :main, :friend, :position, :uncap_level
association :summon, name: :object, blueprint: SummonBlueprint
end
view :full do
include_view :nested
association :party, blueprint: PartyBlueprint, view: :minimal
end
end
end
end

View file

@ -0,0 +1,41 @@
# frozen_string_literal: true
module Api
module V1
class GridWeaponBlueprint < ApiBlueprint
view :uncap do
association :party, blueprint: PartyBlueprint, view: :minimal
fields :position, :uncap_level
end
view :nested do
fields :mainhand, :position, :uncap_level, :element
association :weapon, name: :object, blueprint: WeaponBlueprint
association :weapon_keys,
blueprint: WeaponKeyBlueprint,
if: lambda { |_field_name, w, _options|
[2, 3, 17, 22].include?(w.weapon.series)
}
field :ax, if: ->(_field_name, w, _options) { w.weapon.ax.positive? } do |w|
[
{
modifier: w.ax_modifier1,
strength: w.ax_strength1
},
{
modifier: w.ax_modifier2,
strength: w.ax_strength2
}
]
end
end
view :full do
include_view :nested
association :party, blueprint: PartyBlueprint, view: :minimal
end
end
end
end

View file

@ -0,0 +1,23 @@
# frozen_string_literal: true
module Api
module V1
class JobBlueprint < ApiBlueprint
field :name do |job|
{
en: job.name_en,
ja: job.name_jp
}
end
field :proficiency do |job|
[
job.proficiency1,
job.proficiency2
]
end
fields :row, :ml, :order
end
end
end

View file

@ -0,0 +1,20 @@
# frozen_string_literal: true
module Api
module V1
class JobSkillBlueprint < ApiBlueprint
field :name do |skill|
{
en: skill.name_en,
ja: skill.name_jp
}
end
association :job,
name: :job,
blueprint: JobBlueprint
fields :slug, :color, :main, :base, :sub, :emp, :order
end
end
end

View file

@ -0,0 +1,78 @@
# frozen_string_literal: true
module Api
module V1
class PartyBlueprint < ApiBlueprint
view :weapons do
association :weapons,
blueprint: GridWeaponBlueprint,
view: :nested
end
view :summons do
association :summons,
blueprint: GridSummonBlueprint,
view: :nested
end
view :characters do
association :characters,
blueprint: GridCharacterBlueprint,
view: :nested
end
view :job_skills do
field :job_skills do |job|
{
'0' => !job.skill0.nil? ? JobSkillBlueprint.render_as_hash(job.skill0) : nil,
'1' => !job.skill1.nil? ? JobSkillBlueprint.render_as_hash(job.skill1) : nil,
'2' => !job.skill2.nil? ? JobSkillBlueprint.render_as_hash(job.skill2) : nil,
'3' => !job.skill3.nil? ? JobSkillBlueprint.render_as_hash(job.skill3) : nil
}
end
end
view :minimal do
fields :name, :element, :shortcode, :favorited, :extra, :created_at, :updated_at
association :raid,
blueprint: RaidBlueprint
association :job,
blueprint: JobBlueprint
association :user,
blueprint: UserBlueprint,
view: :minimal
end
view :jobs do
association :job,
blueprint: JobBlueprint
include_view :job_skills
end
view :preview do
include_view :minimal
include_view :weapons
end
view :full do
include_view :preview
include_view :summons
include_view :characters
include_view :job_skills
fields :description, :extra
end
view :collection do
include_view :preview
end
view :destroyed do
fields :name, :description, :created_at, :updated_at
end
end
end
end

View file

@ -0,0 +1,16 @@
# frozen_string_literal: true
module Api
module V1
class RaidBlueprint < ApiBlueprint
field :name do |raid|
{
en: raid.name_en,
ja: raid.name_jp
}
end
fields :slug, :level, :group, :element
end
end
end

View file

@ -0,0 +1,41 @@
# frozen_string_literal: true
module Api
module V1
class SummonBlueprint < ApiBlueprint
field :name do |w|
{
en: w.name_en,
ja: w.name_jp
}
end
fields :granblue_id, :element, :rarity, :max_level
field :uncap do |w|
{
flb: w.flb,
ulb: w.ulb
}
end
field :hp do |w|
{
min_hp: w.min_hp,
max_hp: w.max_hp,
max_hp_flb: w.max_hp_flb,
max_hp_ulb: w.max_hp_ulb
}
end
field :atk do |w|
{
min_atk: w.min_atk,
max_atk: w.max_atk,
max_atk_flb: w.max_atk_flb,
max_atk_ulb: w.max_atk_ulb
}
end
end
end
end

View file

@ -0,0 +1,33 @@
# frozen_string_literal: true
module Api
module V1
class UserBlueprint < ApiBlueprint
view :minimal do
fields :username, :language, :private, :gender
field :avatar do |user|
{
picture: user.picture,
element: user.element
}
end
end
view :profile do
include_view :minimal
field :parties, if: ->(_fn, _obj, options) { options[:parties].length.positive? } do |_, options|
PartyBlueprint.render_as_hash(options[:parties], view: :preview)
end
end
view :token do
fields :username, :token
end
view :settings do
fields :email
end
end
end
end

View file

@ -0,0 +1,43 @@
# frozen_string_literal: true
module Api
module V1
class WeaponBlueprint < ApiBlueprint
field :name do |w|
{
en: w.name_en,
ja: w.name_jp
}
end
fields :granblue_id, :element, :proficiency,
:max_level, :max_skill_level, :limit, :rarity,
:series, :ax
field :uncap do |w|
{
flb: w.flb,
ulb: w.ulb
}
end
field :hp do |w|
{
min_hp: w.min_hp,
max_hp: w.max_hp,
max_hp_flb: w.max_hp_flb,
max_hp_ulb: w.max_hp_ulb
}
end
field :atk do |w|
{
min_atk: w.min_atk,
max_atk: w.max_atk,
max_atk_flb: w.max_atk_flb,
max_atk_ulb: w.max_atk_ulb
}
end
end
end
end

View file

@ -0,0 +1,16 @@
# frozen_string_literal: true
module Api
module V1
class WeaponKeyBlueprint < ApiBlueprint
field :name do |key|
{
en: key.name_en,
ja: key.name_jp
}
end
fields :series, :slot, :group, :order
end
end
end

View file

@ -1,4 +1,7 @@
module Api::V1 # frozen_string_literal: true
module Api
module V1
class ApiController < ActionController::API class ApiController < ActionController::API
##### Doorkeeper ##### Doorkeeper
include Doorkeeper::Rails::Helpers include Doorkeeper::Rails::Helpers
@ -6,7 +9,7 @@ module Api::V1
##### Errors ##### Errors
rescue_from ActiveRecord::RecordInvalid, with: :render_unprocessable_entity_response rescue_from ActiveRecord::RecordInvalid, with: :render_unprocessable_entity_response
rescue_from ActiveRecord::RecordNotDestroyed, with: :render_unprocessable_entity_response rescue_from ActiveRecord::RecordNotDestroyed, with: :render_unprocessable_entity_response
rescue_from ActiveRecord::RecordNotFound, with: :render_not_found_response rescue_from ActiveRecord::RecordNotFound, with: :render_not_found_response_without_object
rescue_from ActiveRecord::RecordNotSaved, with: :render_unprocessable_entity_response rescue_from ActiveRecord::RecordNotSaved, with: :render_unprocessable_entity_response
rescue_from ActiveRecord::RecordNotUnique, with: :render_unprocessable_entity_response rescue_from ActiveRecord::RecordNotUnique, with: :render_unprocessable_entity_response
rescue_from Api::V1::SameFavoriteUserError, with: :render_unprocessable_entity_response rescue_from Api::V1::SameFavoriteUserError, with: :render_unprocessable_entity_response
@ -22,7 +25,7 @@ module Api::V1
##### Hooks ##### Hooks
before_action :current_user before_action :current_user
before_action :set_default_content_type before_action :default_content_type
##### Responders ##### Responders
respond_to :json respond_to :json
@ -34,18 +37,18 @@ module Api::V1
def current_user def current_user
@current_user ||= User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token @current_user ||= User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
return @current_user @current_user
end end
# Set the response content-type # Set the response content-type
def set_content_type(content_type) def content_type(content_type)
response.headers["Content-Type"] = content_type response.headers['Content-Type'] = content_type
end end
# Set the default response content-type to application/javascript # Set the default response content-type to application/javascript
# with a UTF-8 charset # with a UTF-8 charset
def set_default_content_type def default_content_type
set_content_type("application/javascript; charset=utf-8") content_type('application/javascript; charset=utf-8')
end end
### Error response methods ### Error response methods
@ -58,17 +61,33 @@ module Api::V1
end end
def render_unprocessable_entity_response(exception) def render_unprocessable_entity_response(exception)
@exception = exception render json: ErrorBlueprint.render_as_json(nil, exception: exception),
render action: 'errors', status: :unprocessable_entity status: :unprocessable_entity
end end
def render_not_found_response def render_validation_error_response(object)
response = { errors: [{ message: "Record could not be found.", code: "not_found" }] } render json: ErrorBlueprint.render_as_json(nil, errors: object.errors),
render 'not_found', status: :not_found status: :unprocessable_entity
end
def render_not_found_response_without_object
render json: ErrorBlueprint.render(nil,
error: {
message: 'Object could not be found',
code: 'not_found'
}), status: :not_found
end
def render_not_found_response(object)
render json: ErrorBlueprint.render(nil, error: {
message: "#{object.capitalize} could not be found",
code: 'not_found'
}), status: :not_found
end end
def render_unauthorized_response def render_unauthorized_response
render action: 'errors', status: :unauthorized render json: ErrorBlueprint.render_as_json(nil),
status: :unauthorized
end end
private private
@ -77,4 +96,5 @@ module Api::V1
raise UnauthorizedError unless current_user raise UnauthorizedError unless current_user
end end
end end
end
end end

View file

@ -1,41 +1,51 @@
class Api::V1::FavoritesController < Api::V1::ApiController # frozen_string_literal: true
module Api
module V1
class FavoritesController < Api::V1::ApiController
before_action :set_party, only: ['create'] before_action :set_party, only: ['create']
def create def create
party_id = favorite_params[:party_id] party_id = favorite_params[:party_id]
party = Party.find(party_id) party = Party.find(party_id)
if !current_user raise Api::V1::UnauthorizedError unless current_user
raise Api::V1::UnauthorizedError raise Api::V1::SameFavoriteUserError if party.user && current_user.id == party.user.id
elsif party.user && current_user.id == party.user.id raise Api::V1::FavoriteAlreadyExistsError if Favorite.where(user_id: current_user.id,
raise Api::V1::SameFavoriteUserError party_id: party_id).length.positive?
elsif Favorite.where(user_id: current_user.id, party_id: party_id).length > 0
raise Api::V1::FavoriteAlreadyExistsError
else
object = {
user_id: current_user.id,
party_id: favorite_params[:party_id]
}
@favorite = Favorite.new(object) @favorite = Favorite.new({
render :show, status: :created if @favorite.save! user_id: current_user.id,
party_id: party_id
})
if @favorite.save!
return render json: FavoriteBlueprint.render(@favorite, root: :favorite),
status: :created
end end
render_validation_error_response(@favorite)
end end
def destroy def destroy
raise Api::V1::UnauthorizedError unless current_user raise Api::V1::UnauthorizedError unless current_user
@favorite = Favorite.where(user_id: current_user.id, party_id: favorite_params[:party_id]).first @favorite = Favorite.where(user_id: current_user.id, party_id: favorite_params[:party_id]).first
render :destroyed, status: :ok if @favorite && Favorite.destroy(@favorite.id) render_not_found_response('favorite') unless @favorite
render_error("Couldn't delete favorite") unless Favorite.destroy(@favorite.id)
render json: FavoriteBlueprint.render(@favorite, root: :favorite, view: :destroyed)
end end
private private
def set_party def set_party
@party = Party.where("id = ?", params[:party_id]).first @party = Party.where('id = ?', params[:party_id]).first
end end
def favorite_params def favorite_params
params.require(:favorite).permit(:party_id) params.require(:favorite).permit(:party_id)
end end
end
end
end end

View file

@ -1,49 +1,49 @@
class Api::V1::GridCharactersController < Api::V1::ApiController # frozen_string_literal: true
module Api
module V1
class GridCharactersController < Api::V1::ApiController
def create def create
party = Party.find(character_params[:party_id]) party = Party.find(character_params[:party_id])
incoming_character = Character.find(character_params[:character_id]) incoming_character = Character.find(character_params[:character_id])
if current_user render_unauthorized_response if current_user && (party.user != current_user)
if party.user != current_user
render_unauthorized_response
end
end
current_characters = party.characters.map { |c| current_characters = party.characters.map do |c|
Character.find(c.character.id).character_id Character.find(c.character.id).character_id
}.flatten end.flatten
# Check all character ids on incoming character against current characters # Check all character ids on incoming character against current characters
conflict_ids = (current_characters & incoming_character.character_id) conflict_ids = (current_characters & incoming_character.character_id)
if conflict_ids.length > 0 if conflict_ids.length.positive?
# Find conflicting character ids in party characters # Find conflicting character ids in party characters
conflict_characters = party.characters.filter { |c| conflict_characters = party.characters.filter do |c|
c if (conflict_ids & c.character.character_id).length > 0 c if (conflict_ids & c.character.character_id).length.positive?
}.flatten end.flatten
# Render a template with the conflicting and incoming characters, # Render a template with the conflicting and incoming characters,
# as well as the selected position, so the user can be presented with # as well as the selected position, so the user can be presented with
# a decision. # a decision.
# Up to 3 characters can be removed at the same time # Up to 3 characters can be removed at the same time
@conflict_characters = conflict_characters render json: ConflictBlueprint.render(nil, view: :characters,
@incoming_character = incoming_character conflict_characters: conflict_characters,
@incoming_position = character_params[:position] incoming_character: incoming_character,
incoming_position: character_params[:position])
render :conflict, status: :ok
else else
# Replace the grid character in the position if it is already filled # Replace the grid character in the position if it is already filled
if GridCharacter.where(party_id: party.id, position: character_params[:position]).exists? if GridCharacter.where(party_id: party.id, position: character_params[:position]).exists?
@character = GridCharacter.where(party_id: party.id, position: character_params[:position]).limit(1)[0] character = GridCharacter.where(party_id: party.id, position: character_params[:position]).limit(1)[0]
@character.character_id = incoming_character.id character.character_id = incoming_character.id
# Otherwise, create a new grid character # Otherwise, create a new grid character
else else
@character = GridCharacter.create!(character_params.merge(party_id: party.id, character_id: incoming_character.id)) character = GridCharacter.create!(character_params.merge(party_id: party.id,
character_id: incoming_character.id))
end end
render :show, status: :created if @character.save! render json: GridCharacterBlueprint.render(character, view: :nested), status: :created if character.save!
end end
end end
@ -57,9 +57,9 @@ class Api::V1::GridCharactersController < Api::V1::ApiController
# Destroy the character at the desired position if it exists # Destroy the character at the desired position if it exists
existing_character = GridCharacter.where(party: party.id, position: resolve_params[:position]).first existing_character = GridCharacter.where(party: party.id, position: resolve_params[:position]).first
GridCharacter.destroy(existing_character.id) unless !existing_character GridCharacter.destroy(existing_character.id) if existing_character
if (incoming.special) if incoming.special
uncap_level = 3 uncap_level = 3
uncap_level = 5 if incoming.ulb uncap_level = 5 if incoming.ulb
uncap_level = 4 if incoming.flb uncap_level = 4 if incoming.flb
@ -69,34 +69,36 @@ class Api::V1::GridCharactersController < Api::V1::ApiController
uncap_level = 5 if incoming.flb uncap_level = 5 if incoming.flb
end end
@character = GridCharacter.create!(party_id: party.id, character_id: incoming.id, position: resolve_params[:position], uncap_level: uncap_level) character = GridCharacter.create!(party_id: party.id, character_id: incoming.id,
render :show, status: :created if @character.save! position: resolve_params[:position], uncap_level: uncap_level)
render json: GridCharacterBlueprint.render(character, view: :nested), status: :created if character.save!
end end
def update_uncap_level def update_uncap_level
@character = GridCharacter.find(character_params[:id]) character = GridCharacter.find(character_params[:id])
if current_user render_unauthorized_response if current_user && (character.party.user != current_user)
if @character.party.user != current_user
render_unauthorized_response character.uncap_level = character_params[:uncap_level]
end return unless character.save!
render json: GridCharacterBlueprint.render(character, view: :nested, root: :grid_character)
end end
@character.uncap_level = character_params[:uncap_level] # TODO: Implement removing characters
render :show, status: :ok if @character.save! def destroy; end
end
def destroy
end
private private
# Specify whitelisted properties that can be modified. # Specify whitelisted properties that can be modified.
def character_params def character_params
params.require(:character).permit(:id, :party_id, :character_id, :position, :uncap_level, :conflicting, :incoming) params.require(:character).permit(:id, :party_id, :character_id, :position, :uncap_level, :conflicting,
:incoming)
end end
def resolve_params def resolve_params
params.require(:resolve).permit(:position, :incoming, :conflicting => []) params.require(:resolve).permit(:position, :incoming, conflicting: [])
end
end
end end
end end

View file

@ -1,40 +1,38 @@
class Api::V1::GridSummonsController < Api::V1::ApiController # frozen_string_literal: true
module Api
module V1
class GridSummonsController < Api::V1::ApiController
def create def create
party = Party.find(summon_params[:party_id]) party = Party.find(summon_params[:party_id])
canonical_summon = Summon.find(summon_params[:summon_id]) canonical_summon = Summon.find(summon_params[:summon_id])
if current_user render_unauthorized_response if current_user && (party.user != current_user)
if party.user != current_user
render_unauthorized_response
end
end
if grid_summon = GridSummon.where( if (grid_summon = GridSummon.where(
party_id: party.id, party_id: party.id,
position: summon_params[:position] position: summon_params[:position]
).first ).first)
GridSummon.destroy(grid_summon.id) GridSummon.destroy(grid_summon.id)
end end
@summon = GridSummon.create!(summon_params.merge(party_id: party.id, summon_id: canonical_summon.id)) summon = GridSummon.create!(summon_params.merge(party_id: party.id, summon_id: canonical_summon.id))
render :show, status: :created if @summon.save! render json: GridSummonBlueprint.render(summon, view: :nested), status: :created if summon.save!
end end
def update_uncap_level def update_uncap_level
@summon = GridSummon.find(summon_params[:id]) summon = GridSummon.find(summon_params[:id])
if current_user render_unauthorized_response if current_user && (summon.party.user != current_user)
if @summon.party.user != current_user
render_unauthorized_response summon.uncap_level = summon_params[:uncap_level]
end return unless summon.save!
render json: GridSummonBlueprint.render(summon, view: :nested, root: :grid_summon)
end end
@summon.uncap_level = summon_params[:uncap_level] # TODO: Implement removing summons
render :show, status: :ok if @summon.save! def destroy; end
end
def destroy
end
private private
@ -42,4 +40,6 @@ class Api::V1::GridSummonsController < Api::V1::ApiController
def summon_params def summon_params
params.require(:summon).permit(:id, :party_id, :summon_id, :position, :main, :friend, :uncap_level) params.require(:summon).permit(:id, :party_id, :summon_id, :position, :main, :friend, :uncap_level)
end end
end
end
end end

View file

@ -1,39 +1,35 @@
class Api::V1::GridWeaponsController < Api::V1::ApiController # frozen_string_literal: true
before_action :set, except: ['create', 'update_uncap_level', 'destroy']
module Api
module V1
class GridWeaponsController < Api::V1::ApiController
before_action :set, except: %w[create update_uncap_level destroy]
def create def create
party = Party.find(weapon_params[:party_id]) party = Party.find(weapon_params[:party_id])
canonical_weapon = Weapon.find(weapon_params[:weapon_id]) canonical_weapon = Weapon.find(weapon_params[:weapon_id])
if current_user render_unauthorized_response if current_user && (party.user != current_user)
if party.user != current_user
render_unauthorized_response
end
end
if grid_weapon = GridWeapon.where( if (grid_weapon = GridWeapon.where(
party_id: party.id, party_id: party.id,
position: weapon_params[:position] position: weapon_params[:position]
).first ).first)
GridWeapon.destroy(grid_weapon.id) GridWeapon.destroy(grid_weapon.id)
end end
@weapon = GridWeapon.create!(weapon_params.merge(party_id: party.id, weapon_id: canonical_weapon.id)) weapon = GridWeapon.create!(weapon_params.merge(party_id: party.id, weapon_id: canonical_weapon.id))
if (@weapon.position == -1) if weapon.position == -1
party.element = @weapon.weapon.element party.element = weapon.weapon.element
party.save! party.save!
end end
render :show, status: :created if @weapon.save! render json: GridWeaponBlueprint.render(weapon, view: :full), status: :created if weapon.save!
end end
def update def update
if current_user render_unauthorized_response if current_user && (@weapon.party.user != current_user)
if @weapon.party.user != current_user
render_unauthorized_response
end
end
# TODO: Server-side validation of weapon mods # TODO: Server-side validation of weapon mods
# We don't want someone modifying the JSON and adding # We don't want someone modifying the JSON and adding
@ -41,26 +37,28 @@ class Api::V1::GridWeaponsController < Api::V1::ApiController
# Maybe we make methods on the model to validate for us somehow # Maybe we make methods on the model to validate for us somehow
render :update, status: :ok if @weapon.update(weapon_params) render json: GridWeaponBlueprint.render(@weapon, view: :nested) if @weapon.update(weapon_params)
end end
# TODO: Implement removing characters
def destroy; end
def update_uncap_level def update_uncap_level
@weapon = GridWeapon.find(weapon_params[:id]) weapon = GridWeapon.find(weapon_params[:id])
if current_user render_unauthorized_response if current_user && (weapon.party.user != current_user)
if party.user != current_user
render_unauthorized_response
end
end
@weapon.uncap_level = weapon_params[:uncap_level] weapon.uncap_level = weapon_params[:uncap_level]
render :show, status: :ok if @weapon.save! return unless weapon.save!
render json: GridWeaponBlueprint.render(weapon, view: :nested, root: :grid_weapon),
status: :created
end end
private private
def set def set
@weapon = GridWeapon.where("id = ?", params[:id]).first @weapon = GridWeapon.where('id = ?', params[:id]).first
end end
# Specify whitelisted properties that can be modified. # Specify whitelisted properties that can be modified.
@ -72,4 +70,6 @@ class Api::V1::GridWeaponsController < Api::V1::ApiController
:ax_modifier1, :ax_modifier2, :ax_strength1, :ax_strength2 :ax_modifier1, :ax_modifier2, :ax_strength1, :ax_strength2
) )
end end
end
end
end end

View file

@ -1,13 +1,16 @@
class Api::V1::JobSkillsController < Api::V1::ApiController # frozen_string_literal: true
module Api
module V1
class JobSkillsController < Api::V1::ApiController
def all def all
@skills = JobSkill.all() render json: JobSkillBlueprint.render(JobSkill.all)
render :all, status: :ok
end end
def job def job
job = Job.find(params[:id]) @skills = JobSkill.where('job_id != ? AND emp = ?', params[:id], true)
render json: JobSkillBlueprint.render(@skills)
@skills = JobSkill.where(job: job).or(JobSkill.where(sub: true)) end
render :all, status: :ok end
end end
end end

View file

@ -1,15 +1,18 @@
class Api::V1::JobsController < Api::V1::ApiController # frozen_string_literal: true
module Api
module V1
class JobsController < Api::V1::ApiController
before_action :set, only: %w[update_job update_job_skills] before_action :set, only: %w[update_job update_job_skills]
def all def all
@jobs = Job.all() render json: JobBlueprint.render(Job.all)
render :all, status: :ok
end end
def update_job def update_job
raise NoJobProvidedError unless job_params[:job_id].present? if job_params[:job_id] != -1
# Extract job and find its main skills # Extract job and find its main skills
old_job = @party.job
job = Job.find(job_params[:job_id]) job = Job.find(job_params[:job_id])
main_skills = JobSkill.where(job: job.id, main: true) main_skills = JobSkill.where(job: job.id, main: true)
@ -24,7 +27,22 @@ class Api::V1::JobsController < Api::V1::ApiController
@party[key] = nil if @party[key] && mismatched_skill(@party.job, JobSkill.find(@party[key])) @party[key] = nil if @party[key] && mismatched_skill(@party.job, JobSkill.find(@party[key]))
end end
render :update, status: :ok if @party.save! # Remove extra subskills if necessary
if old_job &&
%w[1 2 3].include?(old_job.row) &&
%w[4 5 ex2].include?(job.row) &&
@party.skill1 && @party.skill2 && @party.skill3 &&
@party.skill1.sub && @party.skill2.sub && @party.skill3.sub
@party['skill3_id'] = nil
end
else
@party.job = nil
%w[skill0_id skill1_id skill2_id skill3_id].each do |key|
@party[key] = nil
end
end
render json: PartyBlueprint.render(@party, view: :jobs) if @party.save!
end end
def update_job_skills def update_job_skills
@ -45,7 +63,8 @@ class Api::V1::JobsController < Api::V1::ApiController
new_skill_ids = new_skill_keys.map { |key| job_params[key] } new_skill_ids = new_skill_keys.map { |key| job_params[key] }
new_skill_ids.map do |id| new_skill_ids.map do |id|
skill = JobSkill.find(id) skill = JobSkill.find(id)
raise Api::V1::IncompatibleSkillError.new(job: @party.job, skill: skill) if mismatched_skill(@party.job, skill) raise Api::V1::IncompatibleSkillError.new(job: @party.job, skill: skill) if mismatched_skill(@party.job,
skill)
end end
positions = extract_positions_from_keys(new_skill_keys) positions = extract_positions_from_keys(new_skill_keys)
@ -58,7 +77,7 @@ class Api::V1::JobsController < Api::V1::ApiController
@party.attributes = new_skill_ids @party.attributes = new_skill_ids
end end
render :update, status: :ok if @party.save! render json: PartyBlueprint.render(@party, view: :jobs) if @party.save!
end end
private private
@ -118,16 +137,15 @@ class Api::V1::JobsController < Api::V1::ApiController
end end
def can_add_skill_of_type(skills, position, type) def can_add_skill_of_type(skills, position, type)
if skills.values.compact.length.positive? if %w[4 5 ex2].include?(@party.job.row) && skills.values.compact.length.positive?
max_skill_of_type = 2 max_skill_of_type = 2
skills_to_check = skills.compact.reject { |key, _| key == position } skills_to_check = skills.compact.reject { |key, _| key == position }
sum = skills_to_check.values.count { |value| value.send(type) } sum = skills_to_check.values.count { |value| value.send(type) }
return sum + 1 <= max_skill_of_type
sum + 1 <= max_skill_of_type
else
true
end end
true
end end
def mismatched_skill(job, skill) def mismatched_skill(job, skill)
@ -157,4 +175,6 @@ class Api::V1::JobsController < Api::V1::ApiController
:skill3_id :skill3_id
) )
end end
end
end
end end

View file

@ -1,4 +1,10 @@
class Api::V1::PartiesController < Api::V1::ApiController # frozen_string_literal: true
module Api
module V1
PER_PAGE = 15
class PartiesController < Api::V1::ApiController
before_action :set_from_slug, before_action :set_from_slug,
except: %w[create destroy update index favorites] except: %w[create destroy update index favorites]
before_action :set, only: %w[update destroy] before_action :set, only: %w[update destroy]
@ -7,6 +13,7 @@ class Api::V1::PartiesController < Api::V1::ApiController
@party = Party.new(shortcode: random_string) @party = Party.new(shortcode: random_string)
@party.extra = party_params['extra'] @party.extra = party_params['extra']
# TODO: Extract this into a different method
job = Job.find(party_params['job_id']) if party_params['job_id'].present? job = Job.find(party_params['job_id']) if party_params['job_id'].present?
if job if job
job_skills = JobSkill.where(job: job.id, main: true) job_skills = JobSkill.where(job: job.id, main: true)
@ -17,132 +24,111 @@ class Api::V1::PartiesController < Api::V1::ApiController
@party.user = current_user if current_user @party.user = current_user if current_user
render :show, status: :created if @party.save! if @party.save!
return render json: PartyBlueprint.render(@party, view: :full, root: :party),
status: :created
end
render_validation_error_response(@party)
end end
def show def show
render_not_found_response if @party.nil? return render json: PartyBlueprint.render(@party, view: :full, root: :party) if @party
render_not_found_response('project')
end end
def update def update
if @party.user != current_user render_unauthorized_response if @party.user != current_user
render_unauthorized_response
else
@party.attributes = party_params.except(:skill1_id, :skill2_id, :skill3_id) @party.attributes = party_params.except(:skill1_id, :skill2_id, :skill3_id)
return render json: PartyBlueprint.render(@party, view: :full, root: :party) if @party.save!
render_validation_error_response(@party)
end end
render :update, status: :ok if @party.save! def destroy
render_unauthorized_response if @party.user != current_user
return render json: PartyBlueprint.render(@party, view: :destroyed, root: :checkin) if @party.destroy
end end
def index def index
@per_page = 15 conditions = build_conditions(request.params)
ap conditions
now = DateTime.current @parties = Party.where(conditions)
start_time =
(
now - request.params["recency"].to_i.seconds
).to_datetime.beginning_of_day unless request.params["recency"].blank?
conditions = {}
conditions[:element] = request.params["element"] unless request.params[
"element"
].blank?
conditions[:raid] = request.params["raid"] unless request.params[
"raid"
].blank?
conditions[:created_at] = start_time..now unless request.params[
"recency"
].blank?
conditions[:weapons_count] = 5..13
@parties =
Party
.where(conditions)
.order(created_at: :desc) .order(created_at: :desc)
.paginate(page: request.params[:page], per_page: @per_page) .paginate(page: request.params[:page], per_page: PER_PAGE)
.each do |party| .each { |party| party.favorited = current_user ? party.is_favorited(current_user) : false }
party.favorited =
current_user ? party.is_favorited(current_user) : false
end
@count = Party.where(conditions).count
render :all, status: :ok count = Party.where(conditions).count
total_pages = count.to_f / PER_PAGE > 1 ? (count.to_f / PER_PAGE).ceil : 1
render json: PartyBlueprint.render(@parties,
view: :collection,
root: :results,
meta: {
count: count,
total_pages: total_pages,
per_page: PER_PAGE
})
end end
def favorites def favorites
raise Api::V1::UnauthorizedError unless current_user raise Api::V1::UnauthorizedError unless current_user
@per_page = 15 conditions = build_conditions(request.params)
now = DateTime.current
start_time =
(
now - params["recency"].to_i.seconds
).to_datetime.beginning_of_day unless request.params["recency"].blank?
conditions = {}
conditions[:element] = request.params["element"] unless request.params[
"element"
].blank?
conditions[:raid] = request.params["raid"] unless request.params[
"raid"
].blank?
conditions[:created_at] = start_time..now unless request.params[
"recency"
].blank?
conditions[:favorites] = { user_id: current_user.id } conditions[:favorites] = { user_id: current_user.id }
@parties = @parties = Party.joins(:favorites)
Party
.joins(:favorites)
.where(conditions) .where(conditions)
.order("favorites.created_at DESC") .order('favorites.created_at DESC')
.paginate(page: request.params[:page], per_page: @per_page) .paginate(page: request.params[:page], per_page: PER_PAGE)
.each { |party| party.favorited = party.is_favorited(current_user) } .each { |party| party.favorited = party.is_favorited(current_user) }
@count = Party.joins(:favorites).where(conditions).count
render :all, status: :ok count = Party.joins(:favorites).where(conditions).count
end total_pages = count.to_f / PER_PAGE > 1 ? (count.to_f / PER_PAGE).ceil : 1
def destroy render json: PartyBlueprint.render(@parties,
if @party.user != current_user view: :collection,
render_unauthorized_response root: :results,
elsif @party.destroy meta: {
render :destroyed, status: :ok count: count,
end total_pages: total_pages,
end per_page: PER_PAGE
})
def weapons
render_not_found_response if @party.nil?
render :weapons, status: :ok
end
def summons
render_not_found_response if @party.nil?
render :summons, status: :ok
end
def characters
render_not_found_response if @party.nil?
render :characters, status: :ok
end end
private private
def build_conditions(params)
unless params['recency'].blank?
start_time = (DateTime.current - params['recency'].to_i.seconds)
.to_datetime.beginning_of_day
end
{}.tap do |hash|
hash[:element] = params['element'] unless params['element'].blank?
hash[:raid] = params['raid'] unless params['raid'].blank?
hash[:created_at] = start_time..DateTime.current unless params['recency'].blank?
hash[:weapons_count] = 5..13
end
end
def random_string def random_string
numChars = 6 num_chars = 6
o = [("a".."z"), ("A".."Z"), (0..9)].map(&:to_a).flatten o = [('a'..'z'), ('A'..'Z'), (0..9)].map(&:to_a).flatten
return (0...numChars).map { o[rand(o.length)] }.join (0...num_chars).map { o[rand(o.length)] }.join
end end
def set_from_slug def set_from_slug
@party = Party.where("shortcode = ?", params[:id]).first @party = Party.where('shortcode = ?', params[:id]).first
@party.favorited = @party.favorited = current_user && @party ? @party.is_favorited(current_user) : false
current_user && @party ? @party.is_favorited(current_user) : false
end end
def set def set
@party = Party.where("id = ?", params[:id]).first @party = Party.where('id = ?', params[:id]).first
end end
def party_params def party_params
@ -159,4 +145,6 @@ class Api::V1::PartiesController < Api::V1::ApiController
:skill3_id :skill3_id
) )
end end
end
end
end end

View file

@ -1,6 +1,11 @@
class Api::V1::RaidsController < Api::V1::ApiController # frozen_string_literal: true
module Api
module V1
class RaidsController < Api::V1::ApiController
def all def all
@raids = Raid.all() render json: RaidBlueprint.render(Raid.all)
render :all, status: :ok end
end
end end
end end

View file

@ -1,4 +1,10 @@
class Api::V1::SearchController < Api::V1::ApiController # frozen_string_literal: true
module Api
module V1
PER_PAGE = 10
class SearchController < Api::V1::ApiController
def characters def characters
filters = search_params[:filters] filters = search_params[:filters]
locale = search_params[:locale] || 'en' locale = search_params[:locale] || 'en'
@ -7,12 +13,18 @@ class Api::V1::SearchController < Api::V1::ApiController
if filters if filters
conditions[:rarity] = filters['rarity'] unless filters['rarity'].blank? || filters['rarity'].empty? conditions[:rarity] = filters['rarity'] unless filters['rarity'].blank? || filters['rarity'].empty?
conditions[:element] = filters['element'] unless filters['element'].blank? || filters['element'].empty? conditions[:element] = filters['element'] unless filters['element'].blank? || filters['element'].empty?
conditions[:proficiency1] = filters['proficiency1'] unless filters['proficiency1'].blank? || filters['proficiency1'].empty? unless filters['proficiency1'].blank? || filters['proficiency1'].empty?
conditions[:proficiency2] = filters['proficiency2'] unless filters['proficiency2'].blank? || filters['proficiency2'].empty? conditions[:proficiency1] =
filters['proficiency1']
end
unless filters['proficiency2'].blank? || filters['proficiency2'].empty?
conditions[:proficiency2] =
filters['proficiency2']
end
# conditions[:series] = filters['series'] unless filters['series'].blank? || filters['series'].empty? # conditions[:series] = filters['series'] unless filters['series'].blank? || filters['series'].empty?
end end
@characters = if search_params[:query].present? && search_params[:query].length >= 2 characters = if search_params[:query].present? && search_params[:query].length >= 2
if locale == 'ja' if locale == 'ja'
Character.jp_search(search_params[:query]).where(conditions) Character.jp_search(search_params[:query]).where(conditions)
else else
@ -22,8 +34,16 @@ class Api::V1::SearchController < Api::V1::ApiController
Character.where(conditions) Character.where(conditions)
end end
@count = @characters.length count = characters.length
@characters = @characters.paginate(page: search_params[:page], per_page: 10) paginated = characters.paginate(page: search_params[:page], per_page: PER_PAGE)
render json: CharacterBlueprint.render(paginated,
root: :results,
meta: {
count: count,
total_pages: total_pages(count),
per_page: PER_PAGE
})
end end
def weapons def weapons
@ -34,11 +54,14 @@ class Api::V1::SearchController < Api::V1::ApiController
if filters if filters
conditions[:rarity] = filters['rarity'] unless filters['rarity'].blank? || filters['rarity'].empty? conditions[:rarity] = filters['rarity'] unless filters['rarity'].blank? || filters['rarity'].empty?
conditions[:element] = filters['element'] unless filters['element'].blank? || filters['element'].empty? conditions[:element] = filters['element'] unless filters['element'].blank? || filters['element'].empty?
conditions[:proficiency] = filters['proficiency1'] unless filters['proficiency1'].blank? || filters['proficiency1'].empty? unless filters['proficiency1'].blank? || filters['proficiency1'].empty?
conditions[:proficiency] =
filters['proficiency1']
end
conditions[:series] = filters['series'] unless filters['series'].blank? || filters['series'].empty? conditions[:series] = filters['series'] unless filters['series'].blank? || filters['series'].empty?
end end
@weapons = if search_params[:query].present? && search_params[:query].length >= 2 weapons = if search_params[:query].present? && search_params[:query].length >= 2
if locale == 'ja' if locale == 'ja'
Weapon.jp_search(search_params[:query]).where(conditions) Weapon.jp_search(search_params[:query]).where(conditions)
else else
@ -48,8 +71,16 @@ class Api::V1::SearchController < Api::V1::ApiController
Weapon.where(conditions) Weapon.where(conditions)
end end
@count = @weapons.length count = weapons.length
@weapons = @weapons.paginate(page: search_params[:page], per_page: 10) paginated = weapons.paginate(page: search_params[:page], per_page: PER_PAGE)
render json: WeaponBlueprint.render(paginated,
root: :results,
meta: {
count: count,
total_pages: total_pages(count),
per_page: PER_PAGE
})
end end
def summons def summons
@ -62,7 +93,7 @@ class Api::V1::SearchController < Api::V1::ApiController
conditions[:element] = filters['element'] unless filters['element'].blank? || filters['element'].empty? conditions[:element] = filters['element'] unless filters['element'].blank? || filters['element'].empty?
end end
@summons = if search_params[:query].present? && search_params[:query].length >= 2 summons = if search_params[:query].present? && search_params[:query].length >= 2
if locale == 'ja' if locale == 'ja'
Summon.jp_search(search_params[:query]).where(conditions) Summon.jp_search(search_params[:query]).where(conditions)
else else
@ -72,8 +103,16 @@ class Api::V1::SearchController < Api::V1::ApiController
Summon.where(conditions) Summon.where(conditions)
end end
@count = @summons.length count = summons.length
@summons = @summons.paginate(page: search_params[:page], per_page: 10) paginated = summons.paginate(page: search_params[:page], per_page: PER_PAGE)
render json: SummonBlueprint.render(paginated,
root: :results,
meta: {
count: count,
total_pages: total_pages(count),
per_page: PER_PAGE
})
end end
def job_skills def job_skills
@ -100,7 +139,7 @@ class Api::V1::SearchController < Api::V1::ApiController
end end
# Perform the query # Perform the query
@skills = if search_params[:query].present? && search_params[:query].length >= 2 skills = if search_params[:query].present? && search_params[:query].length >= 2
JobSkill.method("#{locale}_search").call(search_params[:query]) JobSkill.method("#{locale}_search").call(search_params[:query])
.where(conditions) .where(conditions)
.where(job: job.id, main: false) .where(job: job.id, main: false)
@ -108,6 +147,7 @@ class Api::V1::SearchController < Api::V1::ApiController
JobSkill.method("#{locale}_search").call(search_params[:query]) JobSkill.method("#{locale}_search").call(search_params[:query])
.where(conditions) .where(conditions)
.where(sub: true) .where(sub: true)
.where.not(job: job.id)
) )
else else
JobSkill.all JobSkill.all
@ -117,6 +157,7 @@ class Api::V1::SearchController < Api::V1::ApiController
JobSkill.all JobSkill.all
.where(conditions) .where(conditions)
.where(sub: true) .where(sub: true)
.where.not(job: job.id)
) )
.or( .or(
JobSkill.all JobSkill.all
@ -126,14 +167,28 @@ class Api::V1::SearchController < Api::V1::ApiController
) )
end end
@count = @skills.length count = skills.length
@skills = @skills.paginate(page: search_params[:page], per_page: 10) paginated = skills.paginate(page: search_params[:page], per_page: PER_PAGE)
render json: JobSkillBlueprint.render(paginated,
root: :results,
meta: {
count: count,
total_pages: total_pages(count),
per_page: PER_PAGE
})
end end
private private
def total_pages(count)
count.to_f / PER_PAGE > 1 ? (count.to_f / PER_PAGE).ceil : 1
end
# Specify whitelisted properties that can be modified. # Specify whitelisted properties that can be modified.
def search_params def search_params
params.require(:search).permit! params.require(:search).permit!
end end
end
end
end end

View file

@ -1,97 +1,105 @@
class Api::V1::UsersController < Api::V1::ApiController # frozen_string_literal: true
module Api
module V1
PER_PAGE = 15
class UsersController < Api::V1::ApiController
class ForbiddenError < StandardError; end class ForbiddenError < StandardError; end
before_action :set, except: ['create', 'check_email', 'check_username'] before_action :set, except: %w[create check_email check_username]
before_action :set_by_id, only: ['info', 'update'] before_action :set_by_id, only: %w[info update]
def create def create
@user = User.new(user_params) user = User.new(user_params)
if user.save!
token = Doorkeeper::AccessToken.create!( token = Doorkeeper::AccessToken.create!(
application_id: nil, application_id: nil,
resource_owner_id: @user.id, resource_owner_id: user.id,
expires_in: 30.days, expires_in: 30.days,
scopes: 'public' scopes: 'public'
).token ).token
if @user.save! return render json: UserBlueprint.render({
@presenter = { id: user.id,
user_id: @user.id, username: user.username,
username: @user.username,
token: token token: token
} },
view: :token),
render :create, status: :created status: :created
end
end end
render_validation_error_response(@user)
end
def update def update
render :info, status: :ok if @user.update(user_params) render json: UserBlueprint.render(@user, view: :minimal) if @user.update(user_params)
end end
def info def info
render :info, status: :ok render json: UserBlueprint.render(@user, view: :minimal)
end end
def show def show
if @user render_not_found_response('user') unless @user
@per_page = 15
now = DateTime.current conditions = build_conditions(request.params)
start_time = (now - params['recency'].to_i.seconds).to_datetime.beginning_of_day unless request.params['recency'].blank?
conditions = {}
conditions[:element] = request.params['element'] unless request.params['element'].blank?
conditions[:raid] = request.params['raid'] unless request.params['raid'].blank?
conditions[:created_at] = start_time..now unless request.params['recency'].blank?
conditions[:user_id] = @user.id conditions[:user_id] = @user.id
@parties = Party parties = Party
.where(conditions) .where(conditions)
.order(created_at: :desc) .order(created_at: :desc)
.paginate(page: request.params[:page], per_page: @per_page) .paginate(page: request.params[:page], per_page: PER_PAGE)
.each { |party| .each do |party|
party.favorited = (current_user) ? party.is_favorited(current_user) : false party.favorited = current_user ? party.is_favorited(current_user) : false
}
@count = Party.where(conditions).count
else
render_not_found_response
end end
count = Party.where(conditions).count
render json: UserBlueprint.render(@user,
view: :profile,
root: 'profile',
parties: parties,
meta: {
count: count,
total_pages: count.to_f / PER_PAGE > 1 ? (count.to_f / PER_PAGE).ceil : 1,
per_page: PER_PAGE
})
end end
def check_email def check_email
if params[:email].present? render json: EmptyBlueprint.render_as_json(nil, email: params[:email], availability: true)
@available = User.where("email = ?", params[:email]).count == 0
else
@available = false
end
render :available
end end
def check_username def check_username
if params[:username].present? render json: EmptyBlueprint.render_as_json(nil, username: params[:username], availability: true)
@available = User.where("username = ?", params[:username]).count == 0
else
@available = false
end end
render :available def destroy; end
end
def destroy
end
private private
def build_conditions(params)
unless params['recency'].blank?
start_time = (DateTime.current - params['recency'].to_i.seconds)
.to_datetime.beginning_of_day
end
{}.tap do |hash|
hash[:element] = params['element'] unless params['element'].blank?
hash[:raid] = params['raid'] unless params['raid'].blank?
hash[:created_at] = start_time..DateTime.current unless params['recency'].blank?
end
end
# Specify whitelisted properties that can be modified. # Specify whitelisted properties that can be modified.
def set def set
@user = User.where("username = ?", params[:id]).first @user = User.where('username = ?', params[:id]).first
end end
def set_by_id def set_by_id
@user = User.where("id = ?", params[:id]).first @user = User.where('id = ?', params[:id]).first
end end
def user_params def user_params
@ -100,4 +108,6 @@ class Api::V1::UsersController < Api::V1::ApiController
:granblue_id, :picture, :element, :language, :gender, :private :granblue_id, :picture, :element, :language, :gender, :private
) )
end end
end
end
end end

View file

@ -1,11 +1,19 @@
class Api::V1::WeaponKeysController < Api::V1::ApiController # frozen_string_literal: true
def all
conditions = {}
conditions[:series] = request.params['series']
conditions[:slot] = request.params['slot']
conditions[:group] = request.params['group'] unless request.params['group'].blank?
@keys = WeaponKey.where(conditions) module Api
render :all, status: :ok module V1
class WeaponKeysController < Api::V1::ApiController
def all
conditions = {}.tap do |hash|
hash[:series] = request.params['series']
hash[:slot] = request.params['slot']
hash[:group] = request.params['group'] unless request.params['group'].blank?
end
render json: WeaponKeyBlueprint.render(
WeaponKey.where(conditions)
)
end
end
end end
end end

View file

@ -1,6 +1,4 @@
# frozen_string_literal: true
class ApplicationController < ActionController::API class ApplicationController < ActionController::API
# Not usually required for Rails 5 in API mode, but
# necessary here because we're using RABL.
include ActionView::Rendering
append_view_path "#{Rails.root}/app/views"
end end

View file

@ -1,3 +1,5 @@
# frozen_string_literal: true
class TokensController < Doorkeeper::TokensController class TokensController < Doorkeeper::TokensController
# Overriding create action # Overriding create action
# POST /oauth/token # POST /oauth/token
@ -7,7 +9,11 @@ class TokensController < Doorkeeper::TokensController
if response.status == :ok if response.status == :ok
# User the resource_owner_id from token to identify the user # User the resource_owner_id from token to identify the user
user = User.find(response.token.resource_owner_id) rescue nil user = begin
User.find(response.token.resource_owner_id)
rescue StandardError
nil
end
unless user.nil? unless user.nil?
### If you want to render user with template ### If you want to render user with template
@ -25,12 +31,10 @@ class TokensController < Doorkeeper::TokensController
end end
end end
self.headers.merge! response.headers headers.merge! response.headers
self.response_body = body.to_json self.response_body = body.to_json
self.status = response.status self.status = response.status
rescue Doorkeeper::Errors::DoorkeeperError => e rescue Doorkeeper::Errors::DoorkeeperError => e
handle_token_exception e handle_token_exception e
end end
end end

View file

@ -1,22 +0,0 @@
module Api::V1
class FavoriteAlreadyExistsError < GranblueError
def http_status
422
end
def code
"favorite_already_exists"
end
def message
"This user has favorited this party already"
end
def to_hash
{
message: message,
code: code
}
end
end
end

View file

@ -1,29 +0,0 @@
module Api::V1
class IncompatibleSkillError < GranblueError
def initialize(data)
@data = data
end
def http_status
422
end
def code
'incompatible_skill'
end
def message
'The selected skill cannot be added to the current job'
end
def to_hash
ap @data
{
message: message,
code: code,
job: @data[:job],
skill: @data[:skill]
}
end
end
end

View file

@ -1,22 +0,0 @@
module Api::V1
class NoJobProvidedError < GranblueError
def http_status
422
end
def code
"no_job_provided"
end
def message
"A job ID must be provided"
end
def to_hash
{
message: message,
code: code
}
end
end
end

View file

@ -1,22 +0,0 @@
module Api::V1
class NoJobSkillProvidedError < GranblueError
def http_status
422
end
def code
"no_job_skill_provided"
end
def message
"A job skill ID must be provided"
end
def to_hash
{
message: message,
code: code
}
end
end
end

View file

@ -1,22 +0,0 @@
module Api::V1
class UnauthorizedError < StandardError
def http_status
401
end
def code
"unauthorized"
end
def message
"User is not allowed to modify that resource"
end
def to_hash
{
message: message,
code: code
}
end
end
end

View file

@ -0,0 +1,26 @@
# frozen_string_literal: true
module Api
module V1
class FavoriteAlreadyExistsError < GranblueError
def http_status
422
end
def code
'favorite_already_exists'
end
def message
'This user has favorited this party already'
end
def to_hash
{
message: message,
code: code
}
end
end
end
end

View file

@ -4,7 +4,7 @@ module Api
module V1 module V1
# This is the base error that we inherit from for application errors # This is the base error that we inherit from for application errors
class GranblueError < StandardError class GranblueError < StandardError
def initialize(data) def initialize(data = '')
@data = data @data = data
end end

View file

@ -0,0 +1,33 @@
# frozen_string_literal: true
module Api
module V1
class IncompatibleSkillError < GranblueError
def initialize(data)
@data = data
end
def http_status
422
end
def code
'incompatible_skill'
end
def message
'The selected skill cannot be added to the current job'
end
def to_hash
ap @data
{
message: message,
code: code,
job: @data[:job],
skill: @data[:skill]
}
end
end
end
end

View file

@ -0,0 +1,26 @@
# frozen_string_literal: true
module Api
module V1
class NoJobProvidedError < GranblueError
def http_status
422
end
def code
'no_job_provided'
end
def message
'A job ID must be provided'
end
def to_hash
{
message: message,
code: code
}
end
end
end
end

View file

@ -0,0 +1,26 @@
# frozen_string_literal: true
module Api
module V1
class NoJobSkillProvidedError < GranblueError
def http_status
422
end
def code
'no_job_skill_provided'
end
def message
'A job skill ID must be provided'
end
def to_hash
{
message: message,
code: code
}
end
end
end
end

View file

@ -1,3 +1,5 @@
# frozen_string_literal: true
module Api module Api
module V1 module V1
class SameFavoriteUserError < GranblueError class SameFavoriteUserError < GranblueError

View file

@ -0,0 +1,26 @@
# frozen_string_literal: true
module Api
module V1
class UnauthorizedError < StandardError
def http_status
401
end
def code
'unauthorized'
end
def message
'User is not allowed to modify that resource'
end
def to_hash
{
message: message,
code: code
}
end
end
end
end

View file

@ -1,3 +1,5 @@
# frozen_string_literal: true
class ValidationErrorSerializer class ValidationErrorSerializer
def initialize(record, field, details) def initialize(record, field, details)
@record = record @record = record

View file

@ -1,3 +1,4 @@
# frozen_string_literal: true
class ValidationErrorsSerializer class ValidationErrorsSerializer
attr_reader :record attr_reader :record

View file

@ -1,3 +1,5 @@
# frozen_string_literal: true
class ApplicationRecord < ActiveRecord::Base class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true self.abstract_class = true
end end

View file

@ -1,3 +1,5 @@
# frozen_string_literal: true
class Character < ApplicationRecord class Character < ApplicationRecord
include PgSearch::Model include PgSearch::Model
@ -14,10 +16,14 @@ class Character < ApplicationRecord
using: { using: {
tsearch: { tsearch: {
prefix: true, prefix: true,
dictionary: "simple" dictionary: 'simple'
} }
} }
def blueprint
CharacterBlueprint
end
def display_resource(character) def display_resource(character)
character.name_en character.name_en
end end
@ -90,5 +96,4 @@ class Character < ApplicationRecord
# Female: 2, # Female: 2,
# "Male/Female": 3 # "Male/Female": 3
# } # }
end end

View file

@ -1,8 +1,14 @@
# frozen_string_literal: true
class Favorite < ApplicationRecord class Favorite < ApplicationRecord
belongs_to :user belongs_to :user
belongs_to :party belongs_to :party
def party def party
Party.find(self.party_id) Party.find(party_id)
end
def favorite
FavoriteBlueprint
end end
end end

View file

@ -1,7 +1,13 @@
# frozen_string_literal: true
class GridCharacter < ApplicationRecord class GridCharacter < ApplicationRecord
belongs_to :party belongs_to :party
def character def character
Character.find(self.character_id) Character.find(character_id)
end
def blueprint
GridCharacterBlueprint
end end
end end

View file

@ -1,7 +1,13 @@
# frozen_string_literal: true
class GridSummon < ApplicationRecord class GridSummon < ApplicationRecord
belongs_to :party belongs_to :party
def summon def summon
Summon.find(self.summon_id) Summon.find(summon_id)
end
def blueprint
GridSummonBlueprint
end end
end end

View file

@ -1,3 +1,5 @@
# frozen_string_literal: true
class GridWeapon < ApplicationRecord class GridWeapon < ApplicationRecord
belongs_to :party, belongs_to :party,
counter_cache: :weapons_count counter_cache: :weapons_count
@ -7,15 +9,19 @@ class GridWeapon < ApplicationRecord
belongs_to :weapon_key3, class_name: 'WeaponKey', foreign_key: :weapon_key3_id, optional: true belongs_to :weapon_key3, class_name: 'WeaponKey', foreign_key: :weapon_key3_id, optional: true
def weapon def weapon
Weapon.find(self.weapon_id) Weapon.find(weapon_id)
end end
def weapon_keys def weapon_keys
weapon_keys = [] weapon_keys = []
weapon_keys.push(self.weapon_key1) if self.weapon_key1 != nil weapon_keys.push(weapon_key1) unless weapon_key1.nil?
weapon_keys.push(self.weapon_key2) if self.weapon_key2 != nil weapon_keys.push(weapon_key2) unless weapon_key2.nil?
weapon_keys.push(self.weapon_key3) if self.weapon_key3 != nil weapon_keys.push(weapon_key3) unless weapon_key3.nil?
weapon_keys weapon_keys
end end
def blueprint
GridWeaponBlueprint
end
end end

View file

@ -1,3 +1,5 @@
# frozen_string_literal: true
class Job < ApplicationRecord class Job < ApplicationRecord
belongs_to :party belongs_to :party
@ -6,6 +8,10 @@ class Job < ApplicationRecord
class_name: 'Job', class_name: 'Job',
optional: true optional: true
def blueprint
JobBlueprint
end
def display_resource(job) def display_resource(job)
job.name_en job.name_en
end end

View file

@ -1,3 +1,5 @@
# frozen_string_literal: true
class JobSkill < ApplicationRecord class JobSkill < ApplicationRecord
alias eql? == alias eql? ==
@ -10,8 +12,8 @@ class JobSkill < ApplicationRecord
using: { using: {
tsearch: { tsearch: {
prefix: true, prefix: true,
dictionary: "simple", dictionary: 'simple'
}, }
} }
pg_search_scope :jp_search, pg_search_scope :jp_search,
@ -19,15 +21,19 @@ class JobSkill < ApplicationRecord
using: { using: {
tsearch: { tsearch: {
prefix: true, prefix: true,
dictionary: "simple", dictionary: 'simple'
},
} }
}
def blueprint
JobSkillBlueprint
end
def display_resource(skill) def display_resource(skill)
skill.name_en skill.name_en
end end
def ==(o) def ==(other)
self.class == o.class && id == o.id self.class == other.class && id == other.id
end end
end end

View file

@ -1,3 +1,5 @@
# frozen_string_literal: true
class Party < ApplicationRecord class Party < ApplicationRecord
##### ActiveRecord Associations ##### ActiveRecord Associations
belongs_to :user, optional: true belongs_to :user, optional: true
@ -5,38 +7,38 @@ class Party < ApplicationRecord
belongs_to :job, optional: true belongs_to :job, optional: true
belongs_to :skill0, belongs_to :skill0,
foreign_key: "skill0_id", foreign_key: 'skill0_id',
class_name: "JobSkill", class_name: 'JobSkill',
optional: true optional: true
belongs_to :skill1, belongs_to :skill1,
foreign_key: "skill1_id", foreign_key: 'skill1_id',
class_name: "JobSkill", class_name: 'JobSkill',
optional: true optional: true
belongs_to :skill2, belongs_to :skill2,
foreign_key: "skill2_id", foreign_key: 'skill2_id',
class_name: "JobSkill", class_name: 'JobSkill',
optional: true optional: true
belongs_to :skill3, belongs_to :skill3,
foreign_key: "skill3_id", foreign_key: 'skill3_id',
class_name: "JobSkill", class_name: 'JobSkill',
optional: true optional: true
has_many :characters, has_many :characters,
foreign_key: "party_id", foreign_key: 'party_id',
class_name: "GridCharacter", class_name: 'GridCharacter',
dependent: :destroy dependent: :destroy
has_many :weapons, has_many :weapons,
foreign_key: "party_id", foreign_key: 'party_id',
class_name: "GridWeapon", class_name: 'GridWeapon',
dependent: :destroy dependent: :destroy
has_many :summons, has_many :summons,
foreign_key: "party_id", foreign_key: 'party_id',
class_name: "GridSummon", class_name: 'GridSummon',
dependent: :destroy dependent: :destroy
has_many :favorites has_many :favorites
@ -50,23 +52,23 @@ class Party < ApplicationRecord
user.favorite_parties.include? self user.favorite_parties.include? self
end end
def blueprint
PartyBlueprint
end
private private
def skills_are_unique def skills_are_unique
skills = [skill0, skill1, skill2, skill3].compact skills = [skill0, skill1, skill2, skill3].compact
if skills.uniq.length != skills.length return unless skills.uniq.length != skills.length
errors.add(:skill1, "must be unique") if skill0 == skill1
if skill0 == skill2 || skill1 == skill2 errors.add(:skill1, 'must be unique') if skill0 == skill1
errors.add(:skill2, "must be unique")
end
if skill0 == skill3 || skill1 == skill3 || skill2 == skill3 errors.add(:skill2, 'must be unique') if skill0 == skill2 || skill1 == skill2
errors.add(:skill3, "must be unique")
end
errors.add(:job_skills, "must be unique") errors.add(:skill3, 'must be unique') if skill0 == skill3 || skill1 == skill3 || skill2 == skill3
end
errors.add(:job_skills, 'must be unique')
end end
end end

View file

@ -1,2 +1,7 @@
# frozen_string_literal: true
class Raid < ApplicationRecord class Raid < ApplicationRecord
def blueprint
RaidBlueprint
end
end end

View file

@ -1,3 +1,5 @@
# frozen_string_literal: true
class Summon < ApplicationRecord class Summon < ApplicationRecord
include PgSearch::Model include PgSearch::Model
@ -14,10 +16,14 @@ class Summon < ApplicationRecord
using: { using: {
tsearch: { tsearch: {
prefix: true, prefix: true,
dictionary: "simple" dictionary: 'simple'
} }
} }
def blueprint
SummonBlueprint
end
def display_resource(summon) def display_resource(summon)
summon.name_en summon.name_en
end end

View file

@ -1,3 +1,5 @@
# frozen_string_literal: true
class User < ApplicationRecord class User < ApplicationRecord
before_save { self.email = email.downcase } before_save { self.email = email.downcase }
@ -34,10 +36,14 @@ class User < ApplicationRecord
on: :update, on: :update,
if: :password_digest_changed? if: :password_digest_changed?
##### ActiveModel Security ##### ActiveModel Security
has_secure_password has_secure_password
def favorite_parties def favorite_parties
self.favorites.map { |favorite| favorite.party } favorites.map(&:party)
end
def blueprint
UserBlueprint
end end
end end

View file

@ -1,3 +1,5 @@
# frozen_string_literal: true
class Weapon < ApplicationRecord class Weapon < ApplicationRecord
include PgSearch::Model include PgSearch::Model
@ -14,10 +16,14 @@ class Weapon < ApplicationRecord
using: { using: {
tsearch: { tsearch: {
prefix: true, prefix: true,
dictionary: "simple" dictionary: 'simple'
} }
} }
def blueprint
WeaponBlueprint
end
def display_resource(weapon) def display_resource(weapon)
weapon.name_en weapon.name_en
end end

View file

@ -1,2 +1,7 @@
# frozen_string_literal: true
class WeaponKey < ApplicationRecord class WeaponKey < ApplicationRecord
def blueprint
WeaponKeyBlueprint
end
end end

View file

@ -1,18 +0,0 @@
object false
node :errors do
if @exception.respond_to?(:record)
errors = ValidationErrorsSerializer.new(@exception.record).serialize
end
if @exception.respond_to?(:message) && @exception.respond_to?(:code)
errors = [
{
message: @exception.message,
code: @exception.code
}
]
end
errors
end

View file

@ -1,8 +0,0 @@
object false
node(:errors) do
{
'message': "Record could not be found.",
'code': 'not_found'
}
end

View file

@ -1,68 +0,0 @@
object :character
attributes :id,
:granblue_id,
:character_id,
:rarity,
:element,
:gender,
:max_level,
:special
node :name do |w|
{
:en => w.name_en,
:ja => w.name_jp
}
end
node :uncap do |w|
{
:flb => w.flb,
:ulb => w.ulb
}
end
node :hp do |w|
{
:min_hp => w.min_hp,
:max_hp => w.max_hp,
:max_hp_flb => w.max_hp_flb
}
end
node :atk do |w|
{
:min_atk => w.min_atk,
:max_atk => w.max_atk,
:max_atk_flb => w.max_atk_flb
}
end
node :race do |w|
[
w.race1,
w.race2
]
end
node :proficiency do |w|
[
w.proficiency1,
w.proficiency2
]
end
node :data do |w|
{
:base_da => w.base_da,
:base_ta => w.base_ta,
}
end
node :ougi_ratio do |w|
{
:ougi_ratio => w.ougi_ratio,
:ougi_ratio_flb => w.ougi_ratio_flb
}
end

View file

@ -1,3 +0,0 @@
object :favorite
attributes :id, :user_id, :party_id, :created_at, :updated_at

View file

@ -1,5 +0,0 @@
object false
node :destroyed do
true
end

View file

@ -1,3 +0,0 @@
object @favorite
extends 'api/v1/favorites/base'

View file

@ -1,16 +0,0 @@
attributes :id,
:party_id,
:position,
:uncap_level,
:perpetuity,
node :object do |c|
partial("characters/base", :object => c.character)
end
node :awakening do |c|
{
:type => c.awakening_type,
:level => c.awakening_level
}
end

View file

@ -1,14 +0,0 @@
object false
node :conflicts do
partial('grid_characters/base', :object => @conflict_characters)
end
node :incoming do
partial('characters/base', :object => @incoming_character)
end
node :position do
@incoming_position
end

View file

@ -1,3 +0,0 @@
object @character
extends 'api/v1/grid_characters/base'

View file

@ -1,10 +0,0 @@
attributes :id,
:party_id,
:main,
:friend,
:position,
:uncap_level
node :object do |s|
partial('summons/base', :object => s.summon)
end

View file

@ -1,3 +0,0 @@
object @summon
extends 'api/v1/grid_summons/base'

View file

@ -1,34 +0,0 @@
attributes :id,
:party_id,
:mainhand,
:position,
:uncap_level,
:element
node :object do |w|
partial("weapons/base", :object => w.weapon)
end
node :weapon_keys, :if => lambda { |w| [2, 3, 17, 22].include?(w.weapon.series) } do |w|
partial("weapon_keys/base", :object => w.weapon_keys)
end
node :ax, :if => lambda { |w| w.weapon.ax > 0 } do |w|
[
{
:modifier => w.ax_modifier1,
:strength => w.ax_strength1
},
{
:modifier => w.ax_modifier2,
:strength => w.ax_strength2
}
]
end
node :awakening, :if => lambda { |w| w.weapon.awakening } do |w|
{
:type => w.awakening_type,
:level => w.awakening_level
}
end

View file

@ -1,3 +0,0 @@
object @weapon
extends 'api/v1/grid_weapons/base'

View file

@ -1,3 +0,0 @@
object @weapon
extends 'api/v1/grid_weapons/base'

View file

@ -1,3 +0,0 @@
collection @skills, object_root: false
extends 'job_skills/base'

View file

@ -1,10 +0,0 @@
object :job_skill
attributes :id, :job, :slug, :color, :main, :base, :sub, :emp, :order
node :name do |w|
{
:en => w.name_en,
:ja => w.name_jp
}
end

View file

@ -1,3 +0,0 @@
collection @jobs, object_root: false
extends 'jobs/base'

View file

@ -1,17 +0,0 @@
object :job
attributes :id, :row, :ml, :order
node :name do |j|
{
:en => j.name_en,
:ja => j.name_jp
}
end
node :proficiency do |j|
[
j.proficiency1,
j.proficiency2
]
end

View file

@ -1,20 +0,0 @@
object @party
attributes :id, :user_id, :shortcode
node :is_extra do |p|
p.extra
end
node :job do |p|
partial("jobs/base", object: p.job)
end
node :job_skills do |p|
{
"0" => partial("job_skills/base", object: p.skill0),
"1" => partial("job_skills/base", object: p.skill1),
"2" => partial("job_skills/base", object: p.skill2),
"3" => partial("job_skills/base", object: p.skill3),
}
end

View file

@ -1,11 +0,0 @@
node :count do
@count
end
node :total_pages do
(@count.to_f / @per_page > 1) ? (@count.to_f / @per_page).ceil() : 1
end
node(:results) {
partial('parties/base', object: @parties)
} unless @parties.empty?

View file

@ -1,47 +0,0 @@
object :party
attributes :id,
:name,
:description,
:element,
:favorited,
:shortcode,
:created_at,
:updated_at
node :extra do |p|
p.extra
end
node :user do |p|
partial("users/base", object: p.user)
end
node :raid do |p|
partial("raids/base", object: p.raid)
end
node :job do |p|
partial("jobs/base", object: p.job)
end
node :job_skills do |p|
{
"0" => partial("job_skills/base", object: p.skill0),
"1" => partial("job_skills/base", object: p.skill1),
"2" => partial("job_skills/base", object: p.skill2),
"3" => partial("job_skills/base", object: p.skill3),
}
end
node :characters do |p|
partial("grid_characters/base", object: p.characters)
end
node :weapons do |p|
partial("grid_weapons/base", object: p.weapons)
end
node :summons do |p|
partial("grid_summons/base", object: p.summons)
end

View file

@ -1,15 +0,0 @@
object @party
attributes :id, :name, :description, :shortcode, :favorited, :created_at, :updated_at
node :user do |p|
partial('users/base', :object => p.user)
end
node :raid do |p|
partial('raids/base', :object => p.raid)
end
node :characters do |p|
partial('grid_characters/base', :object => p.characters)
end

View file

@ -1,5 +0,0 @@
object false
node :destroyed do
true
end

View file

@ -1,3 +0,0 @@
object @party
extends 'api/v1/parties/base'

View file

@ -1,15 +0,0 @@
object @party
attributes :id, :name, :description, :shortcode, :favorited, :created_at, :updated_at
node :user do |p|
partial('users/base', :object => p.user)
end
node :raid do |p|
partial('raids/base', :object => p.raid)
end
node :summons do |p|
partial('grid_summons/base', :object => p.summons)
end

View file

@ -1,20 +0,0 @@
object @party
attributes :id, :user_id, :shortcode
node :is_extra do |p|
p.extra
end
node :job do |p|
partial("jobs/base", object: p.job)
end
node :job_skills do |p|
{
"0" => partial("job_skills/base", object: p.skill0),
"1" => partial("job_skills/base", object: p.skill1),
"2" => partial("job_skills/base", object: p.skill2),
"3" => partial("job_skills/base", object: p.skill3),
}
end

View file

@ -1,19 +0,0 @@
object @party
attributes :id, :name, :description, :shortcode, :favorited, :created_at, :updated_at
node :user do |p|
partial('users/base', :object => p.user)
end
node :raid do |p|
partial('raids/base', :object => p.raid)
end
node :extra do |p|
p.extra
end
node :weapons do |p|
partial('grid_weapons/base', :object => p.weapons)
end

View file

@ -1,3 +0,0 @@
collection @raids
extends 'raids/base'

View file

@ -1,10 +0,0 @@
object :raid
attributes :id, :slug, :level, :group, :element
node :name do |r|
{
:en => r.name_en,
:ja => r.name_jp
}
end

View file

@ -1,11 +0,0 @@
node :count do
@count
end
node :total_pages do
(@count.to_f / 10 > 1) ? (@count.to_f / 10).ceil() : 1
end
node(:results) {
partial('characters/base', object: @characters)
} unless @characters.empty?

View file

@ -1,11 +0,0 @@
node :count do
@count
end
node :total_pages do
(@count.to_f / 10 > 1) ? (@count.to_f / 10).ceil() : 1
end
node(:results) {
partial('job_skills/base', object: @skills)
} unless @skills.empty?

View file

@ -1,11 +0,0 @@
node :count do
@count
end
node :total_pages do
(@count.to_f / 10 > 1) ? (@count.to_f / 10).ceil() : 1
end
node(:results) {
partial('summons/base', object: @summons)
} unless @summons.empty?

View file

@ -1,11 +0,0 @@
node :count do
@count
end
node :total_pages do
(@count.to_f / 10 > 1) ? (@count.to_f / 10).ceil() : 1
end
node(:results) {
partial('weapons/base', object: @weapons)
} unless @weapons.empty?

View file

@ -1,39 +0,0 @@
object :summon
attributes :id,
:granblue_id,
:element,
:rarity,
:max_level
node :name do |w|
{
:en => w.name_en,
:ja => w.name_jp
}
end
node :uncap do |w|
{
:flb => w.flb,
:ulb => w.ulb
}
end
node :hp do |w|
{
:min_hp => w.min_hp,
:max_hp => w.max_hp,
:max_hp_flb => w.max_hp_flb,
:max_hp_ulb => w.max_hp_ulb
}
end
node :atk do |w|
{
:min_atk => w.min_atk,
:max_atk => w.max_atk,
:max_atk_flb => w.max_atk_flb,
:max_atk_ulb => w.max_atk_ulb
}
end

View file

@ -1,5 +0,0 @@
object false
node(:available) {
@available
}

View file

@ -1,15 +0,0 @@
object :user
attributes :id,
:username,
:granblue_id,
:language,
:private,
:gender
node :picture do |u|
{
:picture => u.picture,
:element => u.element
}
end

View file

@ -1,9 +0,0 @@
object false
node(:user) {
@presenter
} unless @user.blank?
node(:error) {
@error
} unless @error.blank?

View file

@ -1,3 +0,0 @@
object @user
extends 'api/v1/users/base'

Some files were not shown because too many files have changed in this diff Show more