- concern是用来把公共的方法提取到一起,保持代码DRY,是用module来实现的
model中的concern
module Visible
extend ActiveSupport::Concern
VALID_STATUSES = ['public', 'private', 'archived']
included do
belongs_to :user
validates :status, inclusion: { in: VALID_STATUSES }
validate do
errors[:name] << '请输入名称' if name.to_s.splict(',').size < 2
end
scope :public_count, -> { where(status: 'public').count }
def self.public_count
where(status: 'public').count
end
class << self
def public_count
where(status: 'public').count
end
end
def public?
status == 'public'
end
end
class_methods do
def public_count
where(status: 'public').count
end
end
def archived?
status == 'archived'
end
end
class User < ApplicationRecord
include Visible
end
User.public_count
user.archived?
module PubMethods
extend ActiveSupport::Concern
included do
before_action :authenticate_user_using_x_auth_token
rescue_from ActiveRecord::RecordNotFound do |e|
json_response({ msg: e.message }, :not_found)
end
rescue_from StandardError, with: :handle_api_exception
def handle_api_exception(exception)
case exception
when -> (e) { e.message.include?("PG::") || e.message.include?("SQLite3::") }
handle_database_level_exception(exception)
when ActionController::ParameterMissing
render_error(exception, :internal_server_error)
when ActiveRecord::RecordNotFound
render_error(t("not_found", entity: exception.model), :not_found)
when ActiveRecord::RecordNotUnique
render_error(exception)
when ActiveModel::ValidationError, ActiveRecord::RecordInvalid, ArgumentError
error_message = exception.message.gsub("Validation failed: ", "")
render_error(error_message, :unprocessable_entity)
else
handle_generic_exception(exception)
end
end
def handle_generic_exception(exception, status = :internal_server_error)
log_exception(exception) unless Rails.env.test?
error = Rails.env.production? ? t("generic_error") : exception
render_error(error, status)
end
end
def json_response(object, status = :ok)
render json: object, status: status
end
private
def authenticate_user_using_x_auth_token
user_email = request.headers["X-Auth-Email"].presence
auth_token = request.headers["X-Auth-Token"].presence
user = user_email && User.find_by!(email: user_email)
is_valid_token = user && auth_token && ActiveSupport::SecurityUtils.secure_compare(user.authentication_token, auth_token)
if is_valid_token
@current_user = user
else
render_error(t("session.could_not_auth"), :unauthorized)
end
end
def render_error(message, status = :unprocessable_entity, context = {})
is_exception = message.kind_of?(StandardError)
error_message = is_exception ? message.record&.errors_to_sentence : message
render status: status, json: { error: error_message }.merge(context)
end
end
json_response({ msg: 'ok' })