rails_api_base 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fb904521fc43085746d44855945b2705573c9957abceef8691e2d8efd02a8cba
4
+ data.tar.gz: 8a5baa7e4fba53842e804cdb4e92763a372693ac254e0d7cdfba9f54637125f0
5
+ SHA512:
6
+ metadata.gz: 6fa8391f02e591ca8f378a116d2380304a54f76520044018d076aeac9c1a2e6be7c17a3d262178a17fa89f4c6246d72e519bb467ddd1b3dca52fb196f6ffa998
7
+ data.tar.gz: c5caf86b40ef20edd0c33c5df1371a11a9382a2e6cd2addfcb4670e6659880922bdff44ed6e0d65dc5f4c6c76721d21197933b826b2017324f3333f65a8b6c4e
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright aric.zheng
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,19 @@
1
+ # rails_api_base
2
+ > Standardized JSON API base controller for Rails with Blueprinter support.
3
+
4
+ ## Features
5
+
6
+ - Unified response format: `{ code, msg, data }`
7
+ - Field selection via `?fields=title,user`
8
+ - Auto Blueprinter integration (`PostBlueprint`)
9
+ - CRUD scaffolding (index/show/create/update/destroy)
10
+ - Customizable response codes
11
+ - N+1 safe (with proper `includes` in controller)
12
+
13
+ ## Installation
14
+
15
+ Add to your Gemfile:
16
+
17
+ ```ruby
18
+ gem 'rails_api_base'
19
+ gem 'blueprinter'
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ require "bundler/gem_tasks"
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,55 @@
1
+ # app/controllers/concerns/blueprint_options_support.rb
2
+ module BlueprintOptionsSupport
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ # 声明 DSL
7
+ class << self
8
+ def blueprint_options_default(*modes)
9
+ @blueprint_modes = modes
10
+ end
11
+
12
+ def blueprint_modes
13
+ # 支持继承:如果子类没定义,就继承父类的设置
14
+ if instance_variable_defined?(:@blueprint_modes)
15
+ @blueprint_modes
16
+ else
17
+ superclass.respond_to?(:blueprint_modes) ? superclass.blueprint_modes : []
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ # === 主入口 ===
24
+ def blueprint_options
25
+ opts = {}
26
+ self.class.blueprint_modes.each do |mode|
27
+ method_name = "blueprint_options_for_#{mode}"
28
+ if respond_to?(method_name, true)
29
+ opts.merge!(send(method_name))
30
+ else
31
+ Rails.logger.warn("[BlueprintOptionsSupport] Unknown mode: #{mode}")
32
+ end
33
+ end
34
+ opts
35
+ end
36
+
37
+ private
38
+
39
+ # === 模式定义区 ===
40
+ def blueprint_options_for_defaults
41
+ { params: params }
42
+ end
43
+
44
+ def blueprint_options_for_fields
45
+ return {} unless params[:fields].present?
46
+
47
+ fields = params[:fields].split(",").map(&:strip).map(&:to_sym)
48
+ { fields: fields }
49
+ end
50
+
51
+ # 你未来还可以轻松扩展:
52
+ # def blueprint_options_for_locale
53
+ # { locale: I18n.locale }
54
+ # end
55
+ end
@@ -0,0 +1,4 @@
1
+ module RailsApiBase
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,111 @@
1
+ # app/controllers/rails_api_base/base_controller.rb
2
+ module RailsApiBase
3
+ class BaseController < ActionController::API
4
+ include BlueprintOptionsSupport
5
+
6
+ # 默认开启 :defaults 模式
7
+ blueprint_options_default :defaults
8
+
9
+ # === 统一成功响应 ===
10
+ def render_success(data, status: :ok, message: "success", code: nil)
11
+ code ||= response_code_for(action_name, status: status)
12
+ render json: { code: code, msg: message, data: data }, status: status
13
+ end
14
+
15
+ # === 统一错误响应 ===
16
+ def render_error(message: "Unprocessable Entity", status: :unprocessable_entity, errors: nil)
17
+ code = response_code_for(action_name, status: status)
18
+ render json: { code: code, msg: message, errors: errors }, status: status
19
+ end
20
+
21
+ # === 允许子类自定义响应 code ===
22
+ def response_code_for(action, **context)
23
+ status = context[:status] || :ok
24
+ if status.is_a?(Integer)
25
+ status
26
+ else
27
+ Rack::Utils::SYMBOL_TO_STATUS_CODE.fetch(status, 200)
28
+ end
29
+ end
30
+
31
+ # === CRUD 基础动作 ===
32
+ before_action :set_resource, only: %i[show update destroy]
33
+
34
+ def index
35
+ items = collection
36
+ data = serialize_collection(items)
37
+ render_success(data)
38
+ end
39
+
40
+ def show
41
+ data = serialize_resource(resource)
42
+ render_success(data)
43
+ end
44
+
45
+ def create
46
+ resource = resource_class.new(resource_params)
47
+ if resource.save
48
+ data = serialize_resource(resource)
49
+ render_success(data, status: :created, message: "Created successfully")
50
+ else
51
+ render_error(message: "Validation failed", errors: resource.errors.full_messages)
52
+ end
53
+ end
54
+
55
+ def update
56
+ if resource.update(resource_params)
57
+ data = serialize_resource(resource)
58
+ render_success(data, message: "Updated successfully")
59
+ else
60
+ render_error(message: "Validation failed", errors: resource.errors.full_messages)
61
+ end
62
+ end
63
+
64
+ def destroy
65
+ resource.destroy
66
+ render_success(nil, message: "Deleted successfully")
67
+ end
68
+
69
+ private
70
+
71
+ # === 序列化逻辑 ===
72
+ def serialize_resource(resource)
73
+ bp = blueprint_class
74
+ bp ? bp.render_as_hash(resource, **blueprint_options) : resource.as_json
75
+ end
76
+
77
+ def serialize_collection(collection)
78
+ bp = blueprint_class
79
+ bp ? bp.render_as_hash(collection, **blueprint_options) : collection.as_json
80
+ end
81
+
82
+ def blueprint_class
83
+ "#{resource_class}Blueprint".constantize
84
+ rescue NameError
85
+ nil
86
+ end
87
+
88
+ # === 资源推导 ===
89
+ def resource_class
90
+ controller_name.singularize.classify.constantize
91
+ end
92
+
93
+ def resource
94
+ instance_variable_get("@#{controller_name.singularize}")
95
+ end
96
+
97
+ def set_resource
98
+ instance_variable_set("@#{controller_name.singularize}", resource_class.find(params[:id]))
99
+ rescue ActiveRecord::RecordNotFound
100
+ render_error(message: "Record not found", status: :not_found)
101
+ end
102
+
103
+ def collection
104
+ resource_class.all
105
+ end
106
+
107
+ def resource_params
108
+ raise NotImplementedError, "Subclass must implement ##{controller_name.singularize}_params"
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,4 @@
1
+ module RailsApiBase
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module RailsApiBase
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module RailsApiBase
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: "from@example.com"
4
+ layout "mailer"
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module RailsApiBase
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Rails api base</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= yield :head %>
9
+
10
+ <%= stylesheet_link_tag "rails_api_base/application", media: "all" %>
11
+ </head>
12
+ <body>
13
+
14
+ <%= yield %>
15
+
16
+ </body>
17
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ RailsApiBase::Engine.routes.draw do
2
+ end
@@ -0,0 +1,5 @@
1
+ module RailsApiBase
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace RailsApiBase
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module RailsApiBase
2
+ VERSION = "1.0.5"
3
+ end
@@ -0,0 +1,10 @@
1
+ # lib/rails_api_base.rb
2
+ require "blueprinter"
3
+ require "rails_api_base/engine"
4
+
5
+ module RailsApiBase
6
+ # 可选:提供便捷引用
7
+ def self.base_controller
8
+ RailsApiBase::BaseController
9
+ end
10
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :rails_api_base do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails_api_base
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.5
5
+ platform: ruby
6
+ authors:
7
+ - aric.zheng
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2025-11-06 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: rails
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '6.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '6.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: blueprinter
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: kaminari
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ description: Standardized JSON API foundation for Rails apps.
55
+ email:
56
+ - 1290657123@qq.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - MIT-LICENSE
62
+ - README.md
63
+ - Rakefile
64
+ - app/assets/stylesheets/rails_api_base/application.css
65
+ - app/controllers/concerns/blueprint_options_support.rb
66
+ - app/controllers/rails_api_base/application_controller.rb
67
+ - app/controllers/rails_api_base/base_controller.rb
68
+ - app/helpers/rails_api_base/application_helper.rb
69
+ - app/jobs/rails_api_base/application_job.rb
70
+ - app/mailers/rails_api_base/application_mailer.rb
71
+ - app/models/rails_api_base/application_record.rb
72
+ - app/views/layouts/rails_api_base/application.html.erb
73
+ - config/routes.rb
74
+ - lib/rails_api_base.rb
75
+ - lib/rails_api_base/engine.rb
76
+ - lib/rails_api_base/version.rb
77
+ - lib/tasks/rails_api_base_tasks.rake
78
+ homepage: https://js.work
79
+ licenses:
80
+ - MIT
81
+ metadata:
82
+ allowed_push_host: https://rubygems.org
83
+ homepage_uri: https://js.work
84
+ source_code_uri: https://github.com/afeiship/rails_api_base
85
+ changelog_uri: https://github.com/afeiship/rails_api_base/blob/master/CHANGELOG.md
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubygems_version: 3.6.3
101
+ specification_version: 4
102
+ summary: Standardized JSON API foundation for Rails apps.
103
+ test_files: []