From 4031ecd0e3a5816975ef67acad1c8105cabfc70e Mon Sep 17 00:00:00 2001 From: Peter Lejeck Date: Wed, 6 Jul 2016 02:20:31 -0700 Subject: [PATCH] server: general cleanup to solve rubocop complaints --- server/app/models/concerns/age_ratings.rb | 4 +- server/app/models/concerns/episodic.rb | 4 +- server/app/models/concerns/rateable.rb | 13 +- server/app/models/library_entry.rb | 8 +- server/app/models/list_import.rb | 4 +- server/app/models/mapping.rb | 2 +- server/app/models/pro_membership_plan.rb | 4 +- server/app/models/role.rb | 4 +- server/app/models/user.rb | 2 +- server/app/policies/application_policy.rb | 2 +- .../concerns/authenticated_resource.rb | 8 +- .../resources/concerns/searchable_resource.rb | 26 +-- .../app/resources/library_entry_resource.rb | 2 +- server/app/resources/media_resource.rb | 29 +-- server/app/resources/user_resource.rb | 10 +- server/config/environments/development.rb | 4 +- server/config/initializers/rolify.rb | 5 +- server/lib/data_import/http.rb | 3 +- server/lib/data_import/media.rb | 4 +- server/lib/data_import/my_drama_list.rb | 9 +- .../my_drama_list/extractor/cast_list.rb | 46 ++-- .../my_drama_list/extractor/details.rb | 216 +++++++++--------- .../my_drama_list/extractor/episode_list.rb | 42 ++-- .../my_drama_list/extractor/helpers.rb | 16 +- server/lib/jsonapi/search_operation.rb | 7 +- server/lib/jsonapi/searchable_request.rb | 4 +- server/lib/tasks/importers.rake | 16 +- server/lib/unlimited_paginator.rb | 5 +- .../spec/controllers/anime_controller_spec.rb | 10 +- .../library_entries_controller_spec.rb | 10 +- .../spec/controllers/users_controller_spec.rb | 15 +- server/spec/factories/franchises.rb | 2 +- server/spec/factories/manga.rb | 2 +- server/spec/factories/mappings.rb | 2 +- .../formatters/attachment_formatter_spec.rb | 2 +- server/spec/lib/data_import/media_spec.rb | 4 +- .../my_drama_list/extractor/cast_list_spec.rb | 4 +- .../my_drama_list/extractor/details_spec.rb | 14 +- .../extractor/episode_list_spec.rb | 4 +- .../lib/data_import/my_drama_list_spec.rb | 16 +- server/spec/models/library_entry_spec.rb | 16 +- server/spec/models/mapping_spec.rb | 10 +- server/spec/models/user_spec.rb | 26 ++- server/spec/policies/anime_policy_spec.rb | 16 +- server/spec/policies/casting_policy_spec.rb | 6 +- .../policies/library_entry_policy_spec.rb | 3 + server/spec/policies/user_policy_spec.rb | 26 +-- server/spec/support/age_ratings_examples.rb | 1 - server/spec/support/episodic_examples.rb | 4 +- server/spec/support/fixture_helper.rb | 2 +- server/spec/support/media_examples.rb | 4 +- server/spec/support/webmock.rb | 2 +- 52 files changed, 363 insertions(+), 337 deletions(-) diff --git a/server/app/models/concerns/age_ratings.rb b/server/app/models/concerns/age_ratings.rb index fe4342fe5..3e9a760d3 100644 --- a/server/app/models/concerns/age_ratings.rb +++ b/server/app/models/concerns/age_ratings.rb @@ -1,8 +1,8 @@ module AgeRatings extend ActiveSupport::Concern - AGE_RATINGS = %i[G PG R R18] - SAFE_AGE_RATINGS = %w[G PG R] + AGE_RATINGS = %i[G PG R R18].freeze + SAFE_AGE_RATINGS = %w[G PG R].freeze # SFW-ness is whitelist, not blacklist def sfw? diff --git a/server/app/models/concerns/episodic.rb b/server/app/models/concerns/episodic.rb index e12fa9970..dba63c519 100644 --- a/server/app/models/concerns/episodic.rb +++ b/server/app/models/concerns/episodic.rb @@ -5,7 +5,9 @@ def recalculate_episode_length! # Try for the statistical mode (most common value) of episode lengths length, num = episodes.length_mode.values_at(:mode, :count) # If it's less than half of episodes, use average instead - length = episodes.length_average if episode_count && num < (episode_count / 2) + if episode_count && num < (episode_count / 2) + length = episodes.length_average + end update(episode_length: length) end diff --git a/server/app/models/concerns/rateable.rb b/server/app/models/concerns/rateable.rb index f62feb767..5d124e07c 100644 --- a/server/app/models/concerns/rateable.rb +++ b/server/app/models/concerns/rateable.rb @@ -10,25 +10,26 @@ module Rateable def calculate_rating_frequencies base = LibraryEntry::VALID_RATINGS.map { |r| [r, 0] }.to_h - freqs = LibraryEntry.where(media: self).group(:rating).count. - transform_keys(&:to_f).slice(*LibraryEntry::VALID_RATINGS) + freqs = LibraryEntry.where(media: self).group(:rating).count + .transform_keys(&:to_f) + .slice(*LibraryEntry::VALID_RATINGS) base.merge(freqs) end def calculate_rating_frequencies! - self.update_attribute(:rating_frequencies, calculate_rating_frequencies) + update_attribute(:rating_frequencies, calculate_rating_frequencies) end def update_rating_frequency(rating, diff) return if rating.nil? update_query = <<-EOF rating_frequencies = rating_frequencies - || hstore('#{rating.to_s}', ( + || hstore('#{rating}', ( COALESCE(rating_frequencies->'#{rating}', '0')::integer + #{diff} )::text) EOF - self.class.where(id: self.id).update_all(update_query) - self.touch + self.class.where(id: id).update_all(update_query) + touch end def decrement_rating_frequency(rating) diff --git a/server/app/models/library_entry.rb b/server/app/models/library_entry.rb index 864765608..bbf619242 100644 --- a/server/app/models/library_entry.rb +++ b/server/app/models/library_entry.rb @@ -22,7 +22,7 @@ class LibraryEntry < ActiveRecord::Base # TODO: apply this globally so that we can easily update it to add the # totally definitely happening 1000-point scale. Or just because it's good # practice. - VALID_RATINGS = (0.5..5).step(0.5).to_a + VALID_RATINGS = (0.5..5).step(0.5).to_a.freeze belongs_to :user, touch: true belongs_to :media, polymorphic: true @@ -37,7 +37,7 @@ class LibraryEntry < ActiveRecord::Base validates :user, :media, :status, :progress, :reconsume_count, presence: true - validates :user_id, uniqueness: { scope: [:media_type, :media_id] } + validates :user_id, uniqueness: { scope: %i[media_type media_id] } validates :rating, numericality: { greater_than: 0, less_than_or_equal_to: 5 @@ -64,9 +64,7 @@ def progress_limit def rating_on_halves return unless rating - unless rating % 0.5 == 0.0 - errors.add(:rating, 'must be a multiple of 0.5') - end + errors.add(:rating, 'must be a multiple of 0.5') unless rating % 0.5 == 0.0 end after_save do diff --git a/server/app/models/list_import.rb b/server/app/models/list_import.rb index 57efb972c..68cbac6e9 100644 --- a/server/app/models/list_import.rb +++ b/server/app/models/list_import.rb @@ -38,14 +38,14 @@ def apply yield({ status: :running, total: count, current: 0 }) LibraryEntry.transaction do - self.each.with_index do |media, data, index| + each.with_index do |media, data, index| entry = LibraryEntry.where(user: user, media: media).first_or_create merged_entry(entry, data, strategy).save! yield({ status: :running, total: count, current: index + 1 }) end end yield({ status: :completed, total: count, current: count }) - rescue Exception => e + rescue StandardError yield({ status: :error, total: count }) raise end diff --git a/server/app/models/mapping.rb b/server/app/models/mapping.rb index 2f9a103c3..55223d3d1 100644 --- a/server/app/models/mapping.rb +++ b/server/app/models/mapping.rb @@ -14,7 +14,7 @@ class Mapping < ActiveRecord::Base validates :external_site, :external_id, presence: true # Right now, we want to ensure only one external id per media per site - validates :media_id, uniqueness: { scope: [:media_type, :external_site] } + validates :media_id, uniqueness: { scope: %i[media_type external_site] } def self.lookup(site, id) find_by(external_site: site, external_id: id).try(:media) diff --git a/server/app/models/pro_membership_plan.rb b/server/app/models/pro_membership_plan.rb index 790d61272..206d8866f 100644 --- a/server/app/models/pro_membership_plan.rb +++ b/server/app/models/pro_membership_plan.rb @@ -12,6 +12,6 @@ # class ProMembershipPlan < ActiveRecord::Base - scope :recurring, ->{ where(recurring: true) } - scope :nonrecurring, ->{ where(recurring: false) } + scope :recurring, -> { where(recurring: true) } + scope :nonrecurring, -> { where(recurring: false) } end diff --git a/server/app/models/role.rb b/server/app/models/role.rb index 5a5ffd539..09cf64da6 100644 --- a/server/app/models/role.rb +++ b/server/app/models/role.rb @@ -15,8 +15,8 @@ class Role < ActiveRecord::Base belongs_to :resource, polymorphic: true validates :resource_type, - inclusion: { in: Rolify.resource_types }, - allow_nil: true + inclusion: { in: Rolify.resource_types }, + allow_nil: true scopify end diff --git a/server/app/models/user.rb b/server/app/models/user.rb index ef95021cf..23fbd9bf8 100644 --- a/server/app/models/user.rb +++ b/server/app/models/user.rb @@ -69,7 +69,7 @@ class User < ActiveRecord::Base PAST_NAMES_LIMIT = 10 devise :database_authenticatable, :registerable, :recoverable, - :validatable, :confirmable, :async + :validatable, :confirmable, :async rolify belongs_to :pro_membership_plan diff --git a/server/app/policies/application_policy.rb b/server/app/policies/application_policy.rb index 2c01fa0fe..4d6fb5f4a 100644 --- a/server/app/policies/application_policy.rb +++ b/server/app/policies/application_policy.rb @@ -11,7 +11,7 @@ def show? end alias_method :index?, :show? - def is_admin? + def is_admin? # rubocop:disable Style/PredicateName user && user.has_role?(:admin, model_class) end alias_method :create?, :is_admin? diff --git a/server/app/resources/concerns/authenticated_resource.rb b/server/app/resources/concerns/authenticated_resource.rb index 39413c769..0e3e8c828 100644 --- a/server/app/resources/concerns/authenticated_resource.rb +++ b/server/app/resources/concerns/authenticated_resource.rb @@ -19,9 +19,9 @@ def policy # Raise a Pundit::NotAuthorizedError for the given query def not_authorized!(query) - fail Pundit::NotAuthorizedError, query: query, - record: @model, - policy: pundit.policy + raise Pundit::NotAuthorizedError, query: query, + record: @model, + policy: pundit.policy end # Limit scope of relations based on policies @@ -39,7 +39,7 @@ def records_for(relation_name) # Limit scope of finders based on policy class_methods do - def records(options = {context: {}}) + def records(options = { context: {} }) current_user = options[:context][:current_user] policy = Pundit::PolicyFinder.new(_model_class.all) scope = policy.scope.new(current_user, _model_class) diff --git a/server/app/resources/concerns/searchable_resource.rb b/server/app/resources/concerns/searchable_resource.rb index 6178a32ff..0aab66a71 100644 --- a/server/app/resources/concerns/searchable_resource.rb +++ b/server/app/resources/concerns/searchable_resource.rb @@ -12,7 +12,7 @@ def index(index) def inherited(subclass) subclass.instance_variable_set(:@chewy_index, @chewy_index.deep_dup) subclass.instance_variable_set(:@queryable_fields, - @queryable_fields.deep_dup) + @queryable_fields.deep_dup) super end @@ -30,9 +30,7 @@ def query(field, opts = {}) # array all at once, or to modify values. filter field, verify: opts[:verify] || -> (values, context) { if opts[:valid] - if values.all? { |v| opts[:valid].call(v, context) } - values - end + values if values.all? { |v| opts[:valid].call(v, context) } else values end @@ -51,7 +49,7 @@ def should_query?(filters) def search(filters, opts = {}) context = opts[:context] - return [] if filters.values.any? { |f| f.nil? } + return [] if filters.values.any?(&:nil?) # Apply scopes, load, and wrap apply_scopes(filters, opts).load.map { |result| new(result, context) } @@ -59,7 +57,7 @@ def search(filters, opts = {}) # Count all search results def search_count(filters, opts = {}) - return 0 if filters.values.any? { |f| f.nil? } + return 0 if filters.values.any?(&:nil?) apply_scopes(filters, opts).total_count end @@ -71,12 +69,10 @@ def sortable_fields(context = nil) private def apply_scopes(filters, opts = {}) - context = opts[:context] - # Generate query query = generate_query(filters) - query = query.reduce(@chewy_index) do |scope, query| - scope.public_send(*query.values_at(:mode, :query)) + query = query.reduce(@chewy_index) do |scope, subquery| + scope.public_send(*subquery.values_at(:mode, :query)) end # Pagination query = opts[:paginator].apply(query, {}) if opts[:paginator] @@ -98,7 +94,7 @@ def generate_query(filters) filter = filters[field] filter = opts[:apply].call(filter, {}) if opts[:apply] - {mode: opts[:mode] || :filter, query: auto_query(field, filter)} + { mode: opts[:mode] || :filter, query: auto_query(field, filter) } end queries.compact end @@ -106,16 +102,16 @@ def generate_query(filters) def auto_query(field, value) case value when String, Fixnum, Float, Date - {match: {field => value}} + { match: { field => value } } when Range - {range: {field => {gte: value.min, lte: value.max}}} + { range: { field => { gte: value.min, lte: value.max } } } when Array # Array get shorthanded to a single match query - if value.all? { |v| v.is_a?(String) || v.is_a?(Fixnum) || v.is_a?(Float) } + if value.all? { |v| v.is_a?(String) || v.is_a?(Numeric) } auto_query(field, value.join(' ')) else matchers = value.map { |v| auto_query(field, v) } - {bool: {should: matchers}} + { bool: { should: matchers } } end else value diff --git a/server/app/resources/library_entry_resource.rb b/server/app/resources/library_entry_resource.rb index b75bba05e..820bfcdf9 100644 --- a/server/app/resources/library_entry_resource.rb +++ b/server/app/resources/library_entry_resource.rb @@ -2,7 +2,7 @@ class LibraryEntryResource < BaseResource attributes :status, :progress, :reconsuming, :reconsume_count, :notes, - :private, :rating, :updated_at + :private, :rating, :updated_at filters :user_id, :media_id, :media_type, :status diff --git a/server/app/resources/media_resource.rb b/server/app/resources/media_resource.rb index bda1e673f..5b5e1c823 100644 --- a/server/app/resources/media_resource.rb +++ b/server/app/resources/media_resource.rb @@ -2,7 +2,7 @@ class MediaResource < BaseResource # This regex accepts a numerical range or single number # $1 = start, $2 = dot representing closed/open, $3 = end NUMBER = /(\d+(?:\.\d+)?)/ - NUMERIC_RANGE = %r{\A#{NUMBER}(?:(?:\.\.(\.)?)#{NUMBER})?\z} + NUMERIC_RANGE = /\A#{NUMBER}(?:(?:\.\.(\.)?)#{NUMBER})?\z/ NUMERIC_QUERY = { valid: -> (value, _ctx) { NUMERIC_RANGE.match(value) }, apply: -> (values, _ctx) { @@ -17,17 +17,17 @@ class MediaResource < BaseResource end end } - } + }.freeze attributes :slug, :synopsis, - # Images - :poster_image, :cover_image, :cover_image_top_offset, - # Titles - :titles, :canonical_title, :abbreviated_titles, - # Ratings - :average_rating, :rating_frequencies, - # Dates - :start_date, :end_date + # Images + :poster_image, :cover_image, :cover_image_top_offset, + # Titles + :titles, :canonical_title, :abbreviated_titles, + # Ratings + :average_rating, :rating_frequencies, + # Dates + :start_date, :end_date has_many :genres has_many :castings @@ -42,9 +42,10 @@ class MediaResource < BaseResource query :user_count, NUMERIC_QUERY query :genres, apply: -> (values, _ctx) { - {match: {genres: {query: values.join(' '), operator: 'and'}}} + { match: { genres: { query: values.join(' '), operator: 'and' } } } } - query :text, mode: :query, + query :text, + mode: :query, apply: -> (values, _ctx) { { function_score: { @@ -54,7 +55,9 @@ class MediaResource < BaseResource }, query: { multi_match: { - fields: %w[titles.* abbreviated_titles synopsis actors characters], + fields: %w[ + titles.* abbreviated_titles synopsis actors characters + ], query: values.join(','), fuzziness: 2, max_expansions: 15, diff --git a/server/app/resources/user_resource.rb b/server/app/resources/user_resource.rb index ccea798ba..540413812 100644 --- a/server/app/resources/user_resource.rb +++ b/server/app/resources/user_resource.rb @@ -1,12 +1,12 @@ class UserResource < BaseResource - PRIVATE_FIELDS = %i[email password] + PRIVATE_FIELDS = %i[email password].freeze attributes :name, :past_names, :avatar, :cover_image, :about, :bio, - :about_formatted, :location, :website, :waifu_or_husbando, - :rating_system, :to_follow, :followers_count, :following_count, - :onboarded, :life_spent_on_anime + :about_formatted, :location, :website, :waifu_or_husbando, :rating_system, + :to_follow, :followers_count, :following_count, :onboarded, + :life_spent_on_anime - attributes *PRIVATE_FIELDS + attributes(*PRIVATE_FIELDS) filter :name, apply: -> (records, value, _o) { records.by_name(value.first) } filter :self, apply: -> (_r, _v, options) { diff --git a/server/config/environments/development.rb b/server/config/environments/development.rb index 43b07a657..09f599a4a 100644 --- a/server/config/environments/development.rb +++ b/server/config/environments/development.rb @@ -30,8 +30,8 @@ # Enable CORS in Development so Ember can access Rails on a different port config.middleware.insert_before 0, 'Rack::Cors', - debug: true, - logger: -> { Rails.logger } do + debug: true, + logger: -> { Rails.logger } do allow do origins '*' resource '*', headers: :any, diff --git a/server/config/initializers/rolify.rb b/server/config/initializers/rolify.rb index 25a251979..94e9deae4 100644 --- a/server/config/initializers/rolify.rb +++ b/server/config/initializers/rolify.rb @@ -2,6 +2,7 @@ # By default ORM adapter is ActiveRecord. uncomment to use mongoid # config.use_mongoid - # Dynamic shortcuts for User class (user.is_admin? like methods). Default is: false + # Dynamic shortcuts for User class (user.is_admin? like methods). + # Default is: false # config.use_dynamic_shortcuts -end \ No newline at end of file +end diff --git a/server/lib/data_import/http.rb b/server/lib/data_import/http.rb index 27733a1ed..7229e799e 100644 --- a/server/lib/data_import/http.rb +++ b/server/lib/data_import/http.rb @@ -14,6 +14,7 @@ def initialize end private + def queued hydra.queued_requests end @@ -26,7 +27,7 @@ def parallel_get(urls, opts = {}) return urls.each_with_index do |url, i| get(url, opts) do |res| results[i] = res - yield *results if results.compact.length == urls.length + yield(*results) if results.compact.length == urls.length end end end diff --git a/server/lib/data_import/media.rb b/server/lib/data_import/media.rb index d24217ef7..1d418844c 100644 --- a/server/lib/data_import/media.rb +++ b/server/lib/data_import/media.rb @@ -14,8 +14,8 @@ def get_multiple_media(external_ids) # # @param [String] external ID to load # @return [Media] a hash of standardized attributes - def get_media(external_id) - fail 'Override DataImport::Media#get_media with your own implementation' + def get_media(*) + raise 'Override DataImport::Media#get_media with your own implementation' end end end diff --git a/server/lib/data_import/my_drama_list.rb b/server/lib/data_import/my_drama_list.rb index 29118bbfa..7d1c21801 100644 --- a/server/lib/data_import/my_drama_list.rb +++ b/server/lib/data_import/my_drama_list.rb @@ -1,6 +1,6 @@ module DataImport class MyDramaList - MDL_HOST = 'http://mydramalist.com/' + MDL_HOST = 'http://mydramalist.com/'.freeze GENRE_MAPPINGS = { 'Manga' => nil, # Manga-inspired, use Franchise instead 'Detective' => 'Police', # These genres are mostly the same @@ -10,7 +10,7 @@ class MyDramaList 'Sitcom' => 'Comedy', # sitcom is too specific and not a "thing" in JP 'Suspense' => 'Thriller', # suspense is thrilling, right? 'War' => 'Military' # Same thing, different wording - } + }.freeze include DataImport::Media include DataImport::HTTP @@ -34,11 +34,10 @@ def get_media(external_id) cast = Extractor::CastList.new(cast_page) media.assign_attributes(details.to_h) - media.genres = details.genres.map do |genre| + media.genres = details.genres.map { |genre| genre = GENRE_MAPPINGS[genre] if GENRE_MAPPINGS.include? genre Genre.find_by(name: genre) - end.compact - p media.genres + }.compact yield media end end diff --git a/server/lib/data_import/my_drama_list/extractor/cast_list.rb b/server/lib/data_import/my_drama_list/extractor/cast_list.rb index 2517dccb6..50a590d04 100644 --- a/server/lib/data_import/my_drama_list/extractor/cast_list.rb +++ b/server/lib/data_import/my_drama_list/extractor/cast_list.rb @@ -1,30 +1,32 @@ -class DataImport::MyDramaList - module Extractor - class CastList - include Helpers - include Enumerable +module DataImport + class MyDramaList + module Extractor + class CastList + include Helpers + include Enumerable - attr_reader :dom - def initialize(html) - @dom = Nokogiri::HTML(html) - end + attr_reader :dom + def initialize(html) + @dom = Nokogiri::HTML(html) + end - def cast - dom.css('.cast').map do |row| - { - actor: { - id: row.at_css('.cover')['href'].match(/\/(\d+)/)[1], - image: original_for(row.at_css('.cover img')['src']), - name: row.at_css('.name').content.strip - }, - character: { - name: row.at_css('.aka').content.strip, - role: row.at_css('.role').content.strip + def cast + dom.css('.cast').map do |row| + { + actor: { + id: row.at_css('.cover')['href'].match(%r{/(\d+)})[1], + image: original_for(row.at_css('.cover img')['src']), + name: row.at_css('.name').content.strip + }, + character: { + name: row.at_css('.aka').content.strip, + role: row.at_css('.role').content.strip + } } - } + end end + delegate :each, to: :cast end - delegate :each, to: :cast end end end diff --git a/server/lib/data_import/my_drama_list/extractor/details.rb b/server/lib/data_import/my_drama_list/extractor/details.rb index b7ca5b99b..b82d7dc4f 100644 --- a/server/lib/data_import/my_drama_list/extractor/details.rb +++ b/server/lib/data_import/my_drama_list/extractor/details.rb @@ -1,127 +1,129 @@ -class DataImport::MyDramaList - module Extractor - class Details - COUNTRY_CODES = { - 'South Korea' => 'sk', - 'Japan' => 'jp', - 'China' => 'cn', - 'Taiwan' => 'tw', - 'Hong Kong' => 'hk', - 'Thailand' => 'th' - }.freeze - LANGUAGE_CODES = { - 'South Korea' => 'ko', - 'Japan' => 'ja', - 'China' => 'zh', - 'Taiwan' => 'zh', - 'Hong Kong' => 'zh', - 'Thailand' => 'th' - }.freeze - SHOW_TYPES = { - 'Drama' => :drama, - 'Movie' => :movie, - 'Drama Special' => :special - }.freeze - - include Helpers - - attr_reader :dom - def initialize(html) - @dom = Nokogiri::HTML(html) - end +module DataImport + class MyDramaList + module Extractor + class Details + COUNTRY_CODES = { + 'South Korea' => 'sk', + 'Japan' => 'jp', + 'China' => 'cn', + 'Taiwan' => 'tw', + 'Hong Kong' => 'hk', + 'Thailand' => 'th' + }.freeze + LANGUAGE_CODES = { + 'South Korea' => 'ko', + 'Japan' => 'ja', + 'China' => 'zh', + 'Taiwan' => 'zh', + 'Hong Kong' => 'zh', + 'Thailand' => 'th' + }.freeze + SHOW_TYPES = { + 'Drama' => :drama, + 'Movie' => :movie, + 'Drama Special' => :special + }.freeze + + include Helpers + + attr_reader :dom + def initialize(html) + @dom = Nokogiri::HTML(html) + end - def titles - main_title = dom.at_css('h1').content. - gsub("(#{start_date.try(:year)})", '').strip - titles = {} - titles["en_#{country}"] = main_title - titles["#{language}_#{country}"] = details['Native title'] - titles - end + def titles + main_title = dom.at_css('h1').content + .gsub("(#{start_date.try(:year)})", '').strip + titles = {} + titles["en_#{country}"] = main_title + titles["#{language}_#{country}"] = details['Native title'] + titles + end - def canonical_title - "en_#{country}" - end + def canonical_title + "en_#{country}" + end - def abbreviated_titles - (details['Also Known as'] || '').split(';').map(&:strip) - end + def abbreviated_titles + (details['Also Known as'] || '').split(';').map(&:strip) + end - def synopsis - dom.css('.show-synopsis > p').map(&:content).join('\n\n') - end + def synopsis + dom.css('.show-synopsis > p').map(&:content).join('\n\n') + end - def episode_count - (details['Episodes'] || 1).to_i - end + def episode_count + (details['Episodes'] || 1).to_i + end - def episode_length - str = details['Duration'] - parts = str.match(/(?:(?
\d+) hr. )?(?\d+) min./) - (parts['hr'].to_i * 60) + parts['min'].to_i - end + def episode_length + str = details['Duration'] + parts = str.match(/(?:(?
\d+) hr. )?(?\d+) min./) + (parts['hr'].to_i * 60) + parts['min'].to_i + end - def show_type - SHOW_TYPES[details['Type']] - end + def show_type + SHOW_TYPES[details['Type']] + end - def poster_image - original_for dom.at_css('.cover img')['src'] - end + def poster_image + original_for dom.at_css('.cover img')['src'] + end - def start_date - dates[0] - end + def start_date + dates[0] + end - def end_date - dates[1] - end + def end_date + dates[1] + end - def country - COUNTRY_CODES[details['Country']] - end + def country + COUNTRY_CODES[details['Country']] + end - def to_h - %i[titles canonical_title abbreviated_titles synopsis episode_count - episode_length show_type poster_image start_date end_date country - ].map do |k| - [k, send(k)] - end.to_h - end + def to_h + %i[ + titles canonical_title abbreviated_titles synopsis episode_count + episode_length show_type poster_image start_date end_date country + ].map { |k| [k, send(k)] }.to_h + end - def genres - dom.css('.show-genres > a').map(&:content).map(&:strip) - end + def genres + dom.css('.show-genres > a').map(&:content).map(&:strip) + end - private - - def details - @details ||= dom.css('.show-details .txt-block').map do |row| - # Grab the header, strip the whitespace and colon - key = row.at_css('h4').content.strip.sub(/:\z/, '') - # This little XPath query basically queries for *all* nodes (bare - # text included) which are not H4 tags, so we get all the content in - # the row. Once we grab the content, we strip it of whitespace, - # nuke the blank entries, and drop the array if it's singular. - value = row.xpath('node()[not(self::h4)]').map(&:content).map(&:strip) - value.reject!(&:blank?) - value = value.one? ? value.first : value - [key, value] - end.to_h - end + private + + def details + @details ||= dom.css('.show-details .txt-block').map { |row| + # Grab the header, strip the whitespace and colon + key = row.at_css('h4').content.strip.sub(/:\z/, '') + # This little XPath query basically queries for *all* nodes (bare + # text included) which are not H4 tags, so we get all the content in + # the row. Once we grab the content, we strip it of whitespace, + # nuke the blank entries, and drop the array if it's singular. + value = row.xpath('node()[not(self::h4)]').map(&:content) + .map(&:strip) + value.reject!(&:blank?) + value = value.one? ? value.first : value + [key, value] + }.to_h + end - def dates - if details.include? 'Release Date' - [Date.parse(details['Release Date'])] - elsif details.include? 'Aired' - details['Aired'].split('to').map { |d| Date.parse(d) } - else - [] + def dates + if details.include? 'Release Date' + [Date.parse(details['Release Date'])] + elsif details.include? 'Aired' + details['Aired'].split('to').map { |d| Date.parse(d) } + else + [] + end end - end - def language - LANGUAGE_CODES[details['Country']] + def language + LANGUAGE_CODES[details['Country']] + end end end end diff --git a/server/lib/data_import/my_drama_list/extractor/episode_list.rb b/server/lib/data_import/my_drama_list/extractor/episode_list.rb index 0b0e3d376..b26baae62 100644 --- a/server/lib/data_import/my_drama_list/extractor/episode_list.rb +++ b/server/lib/data_import/my_drama_list/extractor/episode_list.rb @@ -1,27 +1,29 @@ -class DataImport::MyDramaList - module Extractor - class EpisodeList - include Helpers - include Enumerable +module DataImport + class MyDramaList + module Extractor + class EpisodeList + include Helpers + include Enumerable - attr_reader :dom - def initialize(html) - @dom = Nokogiri::HTML(html) - end + attr_reader :dom + def initialize(html) + @dom = Nokogiri::HTML(html) + end - def episodes - dom.css('li.episode').map do |row| - thumb = row.at_css('.cover > .mask')['style'].match(/\((.*)\)/)[1] - { - image: original_for(thumb), - title: row.at_css('.title').content, - air_date: row.at_css('.air_date').try(:content), - summary: row.at_css('.summary').at_xpath('text()').try(:content), - number: row.at_css('.title a')['href'].match(/episode\/(\d+)/)[1] - } + def episodes + dom.css('li.episode').map do |row| + thumb = row.at_css('.cover > .mask')['style'].match(/\((.*)\)/)[1] + { + image: original_for(thumb), + title: row.at_css('.title').content, + air_date: row.at_css('.air_date').try(:content), + summary: row.at_css('.summary').at_xpath('text()').try(:content), + number: row.at_css('.title a')['href'].match(%r{episode/(\d+)})[1] + } + end end + delegate :each, to: :episodes end - delegate :each, to: :episodes end end end diff --git a/server/lib/data_import/my_drama_list/extractor/helpers.rb b/server/lib/data_import/my_drama_list/extractor/helpers.rb index 18c2ef4dd..ab09a74af 100644 --- a/server/lib/data_import/my_drama_list/extractor/helpers.rb +++ b/server/lib/data_import/my_drama_list/extractor/helpers.rb @@ -1,12 +1,14 @@ -class DataImport::MyDramaList - module Extractor - module Helpers - extend ActiveSupport::Concern +module DataImport + class MyDramaList + module Extractor + module Helpers + extend ActiveSupport::Concern - private + private - def original_for(src) - src.sub(/_[a-z0-9]+\./, '_f.') + def original_for(src) + src.sub(/_[a-z0-9]+\./, '_f.') + end end end end diff --git a/server/lib/jsonapi/search_operation.rb b/server/lib/jsonapi/search_operation.rb index be6e2ffdd..16f3aee4f 100644 --- a/server/lib/jsonapi/search_operation.rb +++ b/server/lib/jsonapi/search_operation.rb @@ -1,6 +1,6 @@ class SearchOperation < JSONAPI::FindOperation # Filters which we kick to ElasticSearch for processing - SEARCH_FILTERS = %w[text genres year season rating] + SEARCH_FILTERS = %w[text genres year season rating].freeze # Override JSONAPI::FindOperation's apply method to use ElasticSearch where # necessary @@ -18,7 +18,10 @@ def apply if @resource_klass.should_query?(filters) resource_records = @resource_klass.search(filters, find_opts) else - find_opts[:sort_criteria].map! { |x| x[:field] = 'id' if x[:field] == '_score'; x } + find_opts[:sort_criteria].map! do |x| + x[:field] = 'id' if x[:field] == '_score' + x + end resource_records = @resource_klass.find(filters, find_opts) end diff --git a/server/lib/jsonapi/searchable_request.rb b/server/lib/jsonapi/searchable_request.rb index d3cd9fefe..431f927c6 100644 --- a/server/lib/jsonapi/searchable_request.rb +++ b/server/lib/jsonapi/searchable_request.rb @@ -3,7 +3,9 @@ class SearchableRequest < JSONAPI::Request def add_find_operation # Default sort is by {_score: :desc} - @sort_criteria = [{field: '_score', direction: :desc}] unless params[:sort] + unless params[:sort] + @sort_criteria = [{ field: '_score', direction: :desc }] + end @operations.push SearchOperation.new( @resource_klass, diff --git a/server/lib/tasks/importers.rake b/server/lib/tasks/importers.rake index 4a5fddabf..988291c45 100644 --- a/server/lib/tasks/importers.rake +++ b/server/lib/tasks/importers.rake @@ -19,11 +19,13 @@ namespace :importers do Chewy.strategy(:bypass) do puts 'Getting unimported list...' - ids = Anime.find_each.reject do |a| - path = a.send(type).path; path && File.exist?(path) - end.map(&:id) + ids = Anime.find_each.reject { |a| + path = a.send(type).path + File.exist?(path) if path + }.map(&:id) puts "Found #{ids.count}! Prioritizing popular series and limiting..." - ids = Anime.where(id: ids).order(user_count: :desc).limit(quantity).pluck(:id) + ids = Anime.where(id: ids).order(user_count: :desc).limit(quantity) + .pluck(:id) puts "Importing #{ids.count}!" GC.start @@ -46,7 +48,7 @@ namespace :importers do end desc 'Import the bcmoe.json file from disk or (by default) off because.moe' - task :bcmoe, [:filename] => [:environment] do |t, args| + task :bcmoe, [:filename] => [:environment] do |_t, args| # Load the JSON json_file = open(args[:filename] || 'http://because.moe/bcmoe.json').read bcmoe = JSON.parse(json_file).map(&:deep_symbolize_keys) @@ -79,12 +81,12 @@ namespace :importers do subs = spanish ? %w[es] : %w[en] # Output confidence and title mapping - print (' ' * confidence) + ('*' * (5 - confidence)) + ' ' + print((' ' * confidence) + ('*' * (5 - confidence)) + ' ') puts "#{show[:name]} => #{anime.canonical_title}" # Create StreamingLink for each site listed show[:sites].each do |site, url| - link = StreamingLink.where( + StreamingLink.where( streamer: sites[site], url: url, media: anime diff --git a/server/lib/unlimited_paginator.rb b/server/lib/unlimited_paginator.rb index 1ff13cfce..31c2e63ec 100644 --- a/server/lib/unlimited_paginator.rb +++ b/server/lib/unlimited_paginator.rb @@ -8,13 +8,14 @@ class UnlimitedPaginator < OffsetPaginator private + def verify_pagination_params if @limit < 1 - fail JSONAPI::Exceptions::InvalidPageValue.new(:limit, @limit) + raise JSONAPI::Exceptions::InvalidPageValue.new(:limit, @limit) end if @offset < 0 - fail JSONAPI::Exceptions::InvalidPageValue.new(:offset, @offset) + raise JSONAPI::Exceptions::InvalidPageValue.new(:offset, @offset) end end end diff --git a/server/spec/controllers/anime_controller_spec.rb b/server/spec/controllers/anime_controller_spec.rb index 59013706c..a19953513 100644 --- a/server/spec/controllers/anime_controller_spec.rb +++ b/server/spec/controllers/anime_controller_spec.rb @@ -4,14 +4,14 @@ ANIME ||= { titles: { en_jp: String }, canonicalTitle: String - } + }.freeze let(:anime) { create(:anime) } describe '#index' do describe 'with filter[slug]' do it 'should respond with an anime' do get :index, filter: { slug: anime.slug } - expect(response.body).to have_resources(ANIME, 'anime') + expect(response.body).to have_resources(ANIME.dup, 'anime') end end @@ -20,7 +20,7 @@ anime.save! MediaIndex::Anime.import! get :index, filter: { text: anime.canonical_title } - expect(response.body).to have_resources(ANIME, 'anime') + expect(response.body).to have_resources(ANIME.dup, 'anime') end end end @@ -28,7 +28,7 @@ describe '#show' do it 'should respond with an anime' do get :show, id: anime.id - expect(response.body).to have_resource(ANIME, 'anime') + expect(response.body).to have_resource(ANIME.dup, 'anime') end it 'has status ok' do get :show, id: anime.id @@ -69,7 +69,7 @@ def create_anime end it 'should respond with an anime' do create_anime - expect(response.body).to have_resource(ANIME, 'anime') + expect(response.body).to have_resource(ANIME.dup, 'anime') end end end diff --git a/server/spec/controllers/library_entries_controller_spec.rb b/server/spec/controllers/library_entries_controller_spec.rb index 373d23f86..69b0cdc58 100644 --- a/server/spec/controllers/library_entries_controller_spec.rb +++ b/server/spec/controllers/library_entries_controller_spec.rb @@ -34,17 +34,19 @@ end describe 'with logged in user' do - it "should respond with a single private library entry as an array" do + it 'should respond with a single private library entry as an array' do sign_in(user) create(:library_entry, user: user, media: anime, private: true) - 3.times { create(:library_entry, user: build(:user), media: anime, - private: true) } + 3.times do + create(:library_entry, user: build(:user), media: anime, + private: true) + end get :index expect(response.body).to have_resources(LIBRARY_ENTRY, 'libraryEntries') expect(JSON.parse(response.body)['data'].count).to equal(1) end - it "should respond with a list of library entries" do + it 'should respond with a list of library entries' do sign_in(user) create(:library_entry, user: user, media: anime, private: true) 3.times { create(:library_entry, user: build(:user), media: anime) } diff --git a/server/spec/controllers/users_controller_spec.rb b/server/spec/controllers/users_controller_spec.rb index e35f838c9..91a6e8398 100644 --- a/server/spec/controllers/users_controller_spec.rb +++ b/server/spec/controllers/users_controller_spec.rb @@ -1,8 +1,8 @@ require 'rails_helper' RSpec.describe UsersController, type: :controller do - USER ||= { name: String, pastNames: Array } - CURRENT_USER ||= { email: String }.merge(USER) + USER ||= { name: String, pastNames: Array }.freeze + CURRENT_USER ||= { email: String }.merge(USER).freeze let(:user) { create(:user) } describe '#index' do @@ -10,7 +10,7 @@ it 'should respond with a user when authenticated' do sign_in user get :index, filter: { self: 'yes' } - expect(response.body).to have_resources(CURRENT_USER, 'users') + expect(response.body).to have_resources(CURRENT_USER.dup, 'users') expect(response).to have_http_status(:ok) end it 'should respond with an empty list when unauthenticated' do @@ -21,7 +21,8 @@ describe 'with filter[name]' do it 'should find by username' do get :index, filter: { name: user.name } - expect(response.body).to have_resources(USER.merge(name: user.name), 'users') + user_json = USER.merge(name: user.name) + expect(response.body).to have_resources(user_json, 'users') end end end @@ -29,7 +30,7 @@ describe '#show' do it 'should respond with a user' do get :show, id: user.id - expect(response.body).to have_resource(USER, 'users') + expect(response.body).to have_resource(USER.dup, 'users') end it 'has status ok' do get :show, id: user.id @@ -61,7 +62,7 @@ def create_user end it 'should respond with a user' do create_user - expect(response.body).to have_resource(USER, 'users', singular: true) + expect(response.body).to have_resource(USER.dup, 'users', singular: true) end end @@ -89,7 +90,7 @@ def update_user end it 'should respond with a user' do update_user - expect(response.body).to have_resource(USER, 'users', singular: true) + expect(response.body).to have_resource(USER.dup, 'users', singular: true) end end end diff --git a/server/spec/factories/franchises.rb b/server/spec/factories/franchises.rb index 98b231f8d..56e205f03 100644 --- a/server/spec/factories/franchises.rb +++ b/server/spec/factories/franchises.rb @@ -11,7 +11,7 @@ FactoryGirl.define do factory :franchise do - titles { {en_jp: Faker::Name.name} } + titles { { en_jp: Faker::Name.name } } canonical_title 'en_jp' end end diff --git a/server/spec/factories/manga.rb b/server/spec/factories/manga.rb index 9020900fc..3d92a18e8 100644 --- a/server/spec/factories/manga.rb +++ b/server/spec/factories/manga.rb @@ -33,7 +33,7 @@ FactoryGirl.define do factory :manga do - titles { {en_jp: Faker::Name.name} } + titles { { en_jp: Faker::Name.name } } canonical_title 'en_jp' average_rating { rand(1.0..10.0) / 2 } end diff --git a/server/spec/factories/mappings.rb b/server/spec/factories/mappings.rb index f4fedf06e..69f85d760 100644 --- a/server/spec/factories/mappings.rb +++ b/server/spec/factories/mappings.rb @@ -13,6 +13,6 @@ factory :mapping do association :media, factory: :anime external_site 'myanimelist' - external_id { rand(0..50000) } + external_id { rand(0..50_000) } end end diff --git a/server/spec/formatters/attachment_formatter_spec.rb b/server/spec/formatters/attachment_formatter_spec.rb index 6f1a030ef..f0b716305 100644 --- a/server/spec/formatters/attachment_formatter_spec.rb +++ b/server/spec/formatters/attachment_formatter_spec.rb @@ -13,7 +13,7 @@ let(:attachment) do Paperclip::Attachment.new(:file, double, styles: { big: 'test', - small: 'test', + small: 'test' }) end let(:formatted) { subject.format(attachment) } diff --git a/server/spec/lib/data_import/media_spec.rb b/server/spec/lib/data_import/media_spec.rb index 6b568d74f..7c143a5bb 100644 --- a/server/spec/lib/data_import/media_spec.rb +++ b/server/spec/lib/data_import/media_spec.rb @@ -17,8 +17,8 @@ it 'should call #get_media for each and yield what it yields' do allow(subject).to receive(:get_media).and_yield('ohayou') expect { |b| - subject.get_multiple_media(['1234', '5678'], &b) - }.to yield_successive_args(['1234', 'ohayou'], ['5678', 'ohayou']) + subject.get_multiple_media(%w[1234 5678], &b) + }.to yield_successive_args(%w[1234 ohayou], %w[5678 ohayou]) end end end diff --git a/server/spec/lib/data_import/my_drama_list/extractor/cast_list_spec.rb b/server/spec/lib/data_import/my_drama_list/extractor/cast_list_spec.rb index e9369d7f6..b025ad196 100644 --- a/server/spec/lib/data_import/my_drama_list/extractor/cast_list_spec.rb +++ b/server/spec/lib/data_import/my_drama_list/extractor/cast_list_spec.rb @@ -6,7 +6,7 @@ it 'should allow iteration over cast members' do expect(subject.count).to eq(6) - expect(subject).to include({ + expect(subject).to include( actor: { id: '2062', image: 'http://i.mdldb.net/cache/QeQ/z/VLQJ7wz3_7d9ffc_f.jpg', @@ -16,6 +16,6 @@ name: 'Yutaka Daimon', role: 'Main Role' } - }) + ) end end diff --git a/server/spec/lib/data_import/my_drama_list/extractor/details_spec.rb b/server/spec/lib/data_import/my_drama_list/extractor/details_spec.rb index e8d728e54..434ecaa64 100644 --- a/server/spec/lib/data_import/my_drama_list/extractor/details_spec.rb +++ b/server/spec/lib/data_import/my_drama_list/extractor/details_spec.rb @@ -40,13 +40,13 @@ describe '#episode_count' do context 'for a tv series' do - subject { + subject do described_class.new(<<-EOF.strip_heredoc)
  • Episodes:

    16
EOF - } + end it 'should return the number of episodes' do expect(subject.episode_count).to eq(16) end @@ -87,7 +87,7 @@ describe '#poster_image' do it 'should return the fullsize poster' do - expect(subject.poster_image).to include('158866959117997028_2835ca55_f.jpg') + expect(subject.poster_image).to include('_f.jpg') end end @@ -101,13 +101,13 @@ end end context 'for a drama series' do - subject { + subject do described_class.new(<<-EOF.strip_heredoc)
  • Aired:

    Jan 22, 2016 to Mar 12, 2016
EOF - } + end it 'should return the date the first episode aired' do expect(subject.start_date).to eq(Date.new(2016, 1, 22)) end @@ -121,13 +121,13 @@ end end context 'for a drama series' do - subject { + subject do described_class.new(<<-EOF.strip_heredoc)
  • Aired:

    Jan 22, 2016 to Mar 12, 2016
EOF - } + end it 'should return the date the series ended' do expect(subject.end_date).to eq(Date.new(2016, 3, 12)) end diff --git a/server/spec/lib/data_import/my_drama_list/extractor/episode_list_spec.rb b/server/spec/lib/data_import/my_drama_list/extractor/episode_list_spec.rb index 0ef651fa9..b14c456ca 100644 --- a/server/spec/lib/data_import/my_drama_list/extractor/episode_list_spec.rb +++ b/server/spec/lib/data_import/my_drama_list/extractor/episode_list_spec.rb @@ -6,7 +6,7 @@ it 'should allow iteration over episodes' do expect(subject.count).to eq(16) - expect(subject).to include({ + expect(subject).to include( image: 'http://i.mdldb.net/cache/mWb/w/z1dVbjn3_f80ad7_f.jpg', title: 'Signal Episode 1', air_date: 'Jan 22, 2016', @@ -16,6 +16,6 @@ girl from school. But soon, he finds out that the girl is missing and the suspect is a man! Years later, the caseā€¦ EOF - }) + ) end end diff --git a/server/spec/lib/data_import/my_drama_list_spec.rb b/server/spec/lib/data_import/my_drama_list_spec.rb index 9ce35c2cd..ebd7f619b 100644 --- a/server/spec/lib/data_import/my_drama_list_spec.rb +++ b/server/spec/lib/data_import/my_drama_list_spec.rb @@ -4,14 +4,14 @@ subject { described_class.new } before do host = described_class::MDL_HOST - stub_request(:get, "#{host}/123"). - to_return(body: fixture('my_drama_list/karate-robo-zaborgar.html')) - stub_request(:get, "#{host}/123/cast"). - to_return(body: fixture('my_drama_list/karate-robo-zaborgar-cast.html')) - stub_request(:get, "#{host}/123/episodes"). - to_return(body: fixture('my_drama_list/signal-episodes.html')) - stub_request(:get, /i.mdldb.net/). - to_return(body: fixture('image.png'), headers: { + stub_request(:get, "#{host}/123") + .to_return(body: fixture('my_drama_list/karate-robo-zaborgar.html')) + stub_request(:get, "#{host}/123/cast") + .to_return(body: fixture('my_drama_list/karate-robo-zaborgar-cast.html')) + stub_request(:get, "#{host}/123/episodes") + .to_return(body: fixture('my_drama_list/signal-episodes.html')) + stub_request(:get, /i.mdldb.net/) + .to_return(body: fixture('image.png'), headers: { 'Content-Type': 'image/png' }) end diff --git a/server/spec/models/library_entry_spec.rb b/server/spec/models/library_entry_spec.rb index a14657845..31aab7c03 100644 --- a/server/spec/models/library_entry_spec.rb +++ b/server/spec/models/library_entry_spec.rb @@ -29,15 +29,15 @@ it { should validate_presence_of(:status) } it { should validate_presence_of(:progress) } it { should validate_presence_of(:reconsume_count) } - it { - should validate_uniqueness_of(:user_id) - .scoped_to([:media_type, :media_id]) - } - it { - should validate_numericality_of(:rating) + it do + expect(subject).to validate_uniqueness_of(:user_id) + .scoped_to(%i[media_type media_id]) + end + it do + expect(subject).to validate_numericality_of(:rating) .is_less_than_or_equal_to(5) .is_greater_than(0) - } + end describe 'progress_limit validation' do it 'should fail when progress > progress_limit' do @@ -90,7 +90,7 @@ library_entry.save! media.reload freqs = media.rating_frequencies.transform_values(&:to_i) - expect(freqs.values).to all(be_positive.or be_zero) + expect(freqs.values).to all(be_positive.or(be_zero)) end end end diff --git a/server/spec/models/mapping_spec.rb b/server/spec/models/mapping_spec.rb index 1567e34bc..197612b00 100644 --- a/server/spec/models/mapping_spec.rb +++ b/server/spec/models/mapping_spec.rb @@ -17,13 +17,15 @@ it { should validate_presence_of(:media) } it { should validate_presence_of(:external_site) } it { should validate_presence_of(:external_id) } - it { should validate_uniqueness_of(:media_id) - .scoped_to([:media_type, :external_site]) } + it do + expect(subject).to validate_uniqueness_of(:media_id) + .scoped_to(%i[media_type external_site]) + end describe '.lookup' do it 'should respond when it finds the correct media' do anime = create(:anime) - mapping = create(:mapping, media: anime, external_site: 'myanimelist', - external_id: '17') + create(:mapping, media: anime, external_site: 'myanimelist', + external_id: '17') expect(Mapping.lookup('myanimelist', '17')).to eq(anime) end it 'should return nil when it cannot find a matching media' do diff --git a/server/spec/models/user_spec.rb b/server/spec/models/user_spec.rb index 1f6af2f62..041e079df 100644 --- a/server/spec/models/user_spec.rb +++ b/server/spec/models/user_spec.rb @@ -112,39 +112,41 @@ describe 'past_names' do subject { create(:user) } - it 'should include the old name when user changes name for the first time' do - old_name = subject.name - subject.name = 'MisakaMikoto' - subject.save! - expect(subject.past_names).to include(old_name) + context 'when the user changes name for the first time' do + it 'should include the old name' do + old_name = subject.name + subject.name = 'MisakaMikoto' + subject.save! + expect(subject.past_names).to include(old_name) + end end it 'should push onto the front when user changes name multiple times' do - expect do + expect { 3.times do |i| subject.name = "Misaka100#{i}" subject.save! end - end.to change { subject.past_names.length }.by(3) + }.to change { subject.past_names.length }.by(3) end it 'should limit to 10 in length' do - expect do + expect { 20.times do |i| subject.name = "Misaka100#{i}" subject.save! end - end.to change { subject.past_names.length }.from(0).to(10) + }.to change { subject.past_names.length }.from(0).to(10) end it 'should remove duplicate names' do - expect do + expect { 10.times do subject.name = 'MisakaMikoto' subject.save! end - end.to change { subject.past_names.length }.from(0).to(1) + }.to change { subject.past_names.length }.from(0).to(1) end it 'should return first in list when previous_name is called' do 3.times do |i| - subject.name="Misaka100#{i}" + subject.name = "Misaka100#{i}" subject.save end expect(subject.past_names[0]).to equal(subject.previous_name) diff --git a/server/spec/policies/anime_policy_spec.rb b/server/spec/policies/anime_policy_spec.rb index a584f85b6..442b41dbd 100644 --- a/server/spec/policies/anime_policy_spec.rb +++ b/server/spec/policies/anime_policy_spec.rb @@ -11,19 +11,19 @@ permissions :show? do context 'for sfw' do - it ('should allow users') { should permit(user, anime) } - it ('should allow anons') { should permit(nil, anime) } + it('should allow users') { should permit(user, anime) } + it('should allow anons') { should permit(nil, anime) } end context 'for nsfw' do - it ('should not allow anons') { should_not permit(nil, hentai) } - it ('should not allow kids') { should_not permit(user, hentai) } - it ('should allow perverts') { should permit(pervert, hentai) } + it('should not allow anons') { should_not permit(nil, hentai) } + it('should not allow kids') { should_not permit(user, hentai) } + it('should allow perverts') { should permit(pervert, hentai) } end end permissions :create?, :update?, :destroy? do - it ('should allow admins') { should permit(admin, anime) } - it ('should not allow normal users') { should_not permit(user, anime) } - it ('should not allow anon') { should_not permit(nil, anime) } + it('should allow admins') { should permit(admin, anime) } + it('should not allow normal users') { should_not permit(user, anime) } + it('should not allow anon') { should_not permit(nil, anime) } end end diff --git a/server/spec/policies/casting_policy_spec.rb b/server/spec/policies/casting_policy_spec.rb index 5f13fb4eb..47396de9d 100755 --- a/server/spec/policies/casting_policy_spec.rb +++ b/server/spec/policies/casting_policy_spec.rb @@ -8,8 +8,8 @@ subject { described_class } permissions :show? do - it ('should allow anons') { should permit(nil, casting) } - it ('should allow users') { should permit(user, casting) } - it ('should allow admins') { should permit(admin, casting) } + it('should allow anons') { should permit(nil, casting) } + it('should allow users') { should permit(user, casting) } + it('should allow admins') { should permit(admin, casting) } end end diff --git a/server/spec/policies/library_entry_policy_spec.rb b/server/spec/policies/library_entry_policy_spec.rb index e9bb447f5..db63448d6 100644 --- a/server/spec/policies/library_entry_policy_spec.rb +++ b/server/spec/policies/library_entry_policy_spec.rb @@ -7,6 +7,8 @@ let(:entry) { build(:library_entry, user: owner) } subject { described_class } + # (it's much cleaner on one line) + # rubocop:disable Metrics/LineLength permissions :show? do let(:pervert) { build(:user, sfw_filter: false) } let(:hentai_entry) { build(:library_entry, :nsfw, user: owner) } @@ -37,6 +39,7 @@ it('should allow private entries') { should permit(admin, private_entry) } end end + # rubocop:enable Metrics/LineLength permissions :create?, :update?, :destroy? do it('should allow owner') { should permit(owner, entry) } diff --git a/server/spec/policies/user_policy_spec.rb b/server/spec/policies/user_policy_spec.rb index 72d85dd59..628f6b6ea 100755 --- a/server/spec/policies/user_policy_spec.rb +++ b/server/spec/policies/user_policy_spec.rb @@ -7,31 +7,31 @@ subject { described_class } permissions :show? do - it ('should allow anons') { should permit(nil, other) } - it ('should allow users') { should permit(user, other) } + it('should allow anons') { should permit(nil, other) } + it('should allow users') { should permit(user, other) } end permissions :create? do - it ('should allow admins') { should permit(admin, other) } - it ('should allow normal users') { should permit(user, other) } - it ('should allow anon') { should permit(nil, other) } + it('should allow admins') { should permit(admin, other) } + it('should allow normal users') { should permit(user, other) } + it('should allow anon') { should permit(nil, other) } end permissions :update? do context 'for self' do - it ('should allow normal users') { should permit(user, user) } - it ('should allow admins') { should permit(admin, admin) } + it('should allow normal users') { should permit(user, user) } + it('should allow admins') { should permit(admin, admin) } end context 'for other' do - it ('should not allow normal users') { should_not permit(user, other) } - it ('should not allow anons') { should_not permit(nil, other) } - it ('should allow admins') { should permit(admin, other) } + it('should not allow normal users') { should_not permit(user, other) } + it('should not allow anons') { should_not permit(nil, other) } + it('should allow admins') { should permit(admin, other) } end end permissions :destroy? do - it ('should allow admins') { should permit(admin, other) } - it ('should not allow normal users') { should_not permit(user, other) } - it ('should not allow anon') { should_not permit(nil, other) } + it('should allow admins') { should permit(admin, other) } + it('should not allow normal users') { should_not permit(user, other) } + it('should not allow anon') { should_not permit(nil, other) } end end diff --git a/server/spec/support/age_ratings_examples.rb b/server/spec/support/age_ratings_examples.rb index f57c188f3..45126922f 100644 --- a/server/spec/support/age_ratings_examples.rb +++ b/server/spec/support/age_ratings_examples.rb @@ -26,5 +26,4 @@ expect(Anime.sfw.count).to eq(5) end end - end diff --git a/server/spec/support/episodic_examples.rb b/server/spec/support/episodic_examples.rb index 0d672132a..c9531e56c 100644 --- a/server/spec/support/episodic_examples.rb +++ b/server/spec/support/episodic_examples.rb @@ -9,13 +9,13 @@ describe '#recalculate_episode_length!' do it 'should set episode_length to the mode when it is more than 50%' do anime = create(:anime, episode_count: 10) - expect(Episode).to receive(:length_mode) { {mode: 5, count: 8} } + expect(Episode).to receive(:length_mode) { { mode: 5, count: 8 } } expect(anime).to receive(:update).with(episode_length: 5) anime.recalculate_episode_length! end it 'should set episode_length to the mean when mode is less than 50%' do anime = create(:anime, episode_count: 10) - allow(Episode).to receive(:length_mode) { {mode: 5, count: 2} } + allow(Episode).to receive(:length_mode) { { mode: 5, count: 2 } } expect(Episode).to receive(:length_average) { 10 } expect(anime).to receive(:update).with(episode_length: 10) anime.recalculate_episode_length! diff --git a/server/spec/support/fixture_helper.rb b/server/spec/support/fixture_helper.rb index 8132b8dd0..f4d1a3471 100644 --- a/server/spec/support/fixture_helper.rb +++ b/server/spec/support/fixture_helper.rb @@ -1,6 +1,6 @@ class Fixture attr_accessor :name, :filename, :content - @@cache = Hash.new { |h,k| h[k] = {} } + @@cache = Hash.new { |h, k| h[k] = {} } def initialize(name, opts = {}) @name = name diff --git a/server/spec/support/media_examples.rb b/server/spec/support/media_examples.rb index 0e61a6f90..bd7d32b96 100644 --- a/server/spec/support/media_examples.rb +++ b/server/spec/support/media_examples.rb @@ -17,11 +17,11 @@ it { should respond_to(:slug_candidates) } it { should respond_to(:progress_limit) } it { should delegate_method(:year).to(:start_date) } - it { + it 'should ensure rating is within 0..5' do should validate_numericality_of(:average_rating) .is_less_than_or_equal_to(5) .is_greater_than(0) - } + end describe '#calculate_rating_frequencies' do context 'with no library entries' do diff --git a/server/spec/support/webmock.rb b/server/spec/support/webmock.rb index 079abf14c..9ee81a34d 100644 --- a/server/spec/support/webmock.rb +++ b/server/spec/support/webmock.rb @@ -2,6 +2,6 @@ WebMock.disable_net_connect!(allow: [ 'robohash.org', - %r[pigment.github.io/fake-logos], + %r{pigment.github.io/fake-logos}, 'localhost' ])