trax_controller 0.1.2 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2a0c3f89d4a18d3f4a2a657426d3cbbc171b2ebb
4
- data.tar.gz: a6c561ef139611f7428793d35e2020c04e47b5cb
2
+ SHA256:
3
+ metadata.gz: ed00dea1fdfcffa650fe001af13c9903a9e8cea3f8bcfaa1c944440c2ef8d293
4
+ data.tar.gz: f34a3dcd374fb0adddb5b126cc5e1f9a5ab69520ac1902e8b5399a2bf1e475cc
5
5
  SHA512:
6
- metadata.gz: 8233b8ef9a6fb515e44e666bc42af3749c1c00790e2fc094c88b0d0d1f45fdf5d8cf5da6045855fdb45e3f46385556022d6297f039eba32c64d7fa9168b0df2d
7
- data.tar.gz: 40c8a347d7552ba34035bf9264222b699d2ff0ae96d42762d401a06c20643017d8e2d98f1b18cd057ad0008db853b5d0fd65d60cd0723482bc6e040fbbd33f6e
6
+ metadata.gz: 9ff8023e73a5c5d27b0f337fccdc0f337fb5f4f91ec3e3ebbd5a4bce75c9fefa4c3373159848e86867ee3686e662e0eda6cec8814ac2f8cb830a5632731f34eb
7
+ data.tar.gz: 658915adb99f4b46f3fdb160abe4b217dccad146584df53949ddc47708ac3f9761bd7eb1baaae46e30d2b3d5619d4e998aa45a1380b38d31814bad7be55ba5b2
data/.gitignore CHANGED
@@ -7,8 +7,10 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ /vendor/
10
11
  *.bundle
11
12
  *.so
12
13
  *.o
13
14
  *.a
15
+ *.sqlite
14
16
  mkmf.log
data/Gemfile CHANGED
@@ -2,8 +2,6 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in trax_controller.gemspec
4
4
  gemspec
5
- # gem 'active_model_serializers', :github => 'rails-api/active_model_serializers', :branch => "0-10-stable"
6
- gem 'active_model_serializers', :github => 'rails-api/active_model_serializers', :branch => "0-10-stable", :ref => "6aba26049154712d65176708ffad55fcfe512ca0"
7
5
 
8
6
  group :test do
9
7
  gem 'activerecord'
@@ -88,6 +88,16 @@ module Trax
88
88
  collection_root.singularize
89
89
  end
90
90
 
91
+ #this overwrite allows a separate set of params to be used for create/update
92
+ #i.e. product_params_for_create, product_params_for_update
93
+ def resource_params_method_name
94
+ if respond_to?("#{resource_instance_name}_params_for_#{params[:action]}", true)
95
+ "#{resource_instance_name}_params_for_#{params[:action]}"
96
+ else
97
+ super
98
+ end
99
+ end
100
+
91
101
  #will set the resource instance var to whatever you pass it, then render
92
102
  def render_resource!(object, **options)
93
103
  instance_variable_set(:"@#{self.class.resources_configuration[:self][:instance_name]}", object)
@@ -108,6 +118,17 @@ module Trax
108
118
  render json: { meta: { errors: errors } }, status: status, serializer: nil
109
119
  end
110
120
 
121
+ def render_resource_action_response(success_status: 200, failure_status: :method_not_allowed, **options)
122
+ respond_with_dual_blocks(resource, options) do |success, failure|
123
+ success.json do
124
+ render_resource(success_status, **options)
125
+ end
126
+ failure.json do
127
+ render_errors(failure_status, **options)
128
+ end
129
+ end
130
+ end
131
+
111
132
  def resource_error_messages(resource: _resource, **options)
112
133
  return nil unless resource.errors.any?
113
134
 
@@ -0,0 +1,29 @@
1
+ module Trax
2
+ module Controller
3
+ module Collection
4
+ module NestedSearchScopes
5
+ extend ::ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ def has_nested_scopes_for(scope_name, as:, model:, permitted_scopes: [], only: [:index, :search], type: :hash, **options)
9
+ has_scope(scope_name, as: as, only: only, type: type, **options) do |controller, scope, value|
10
+ scope_ivar_name = "@#{scope_name}_scope"
11
+ instance_variable_set(:"#{scope_ivar_name}", model)
12
+
13
+ value.each_pair do |k,v|
14
+ raise ::ActionController::ParameterMissing.new("Invalid search parameter #{k} #{v}") unless permitted_scopes.include?(k)
15
+
16
+ instance_variable_set(
17
+ :"#{scope_ivar_name}",
18
+ instance_variable_get(:"#{scope_ivar_name}").all.__send__(k, v)
19
+ )
20
+ end
21
+
22
+ scope.__send__(scope_name, instance_variable_get(:"#{scope_ivar_name}"))
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,24 @@
1
+ module Trax
2
+ module Controller
3
+ module Collection
4
+ module Sortable
5
+ extend ::ActiveSupport::Concern
6
+
7
+ SORT_DIRECTIONS = [ "asc", "desc" ].freeze
8
+
9
+ module ClassMethods
10
+ def has_sort_scope(sort_scope_name, only: [:index, :search], type: :boolean, **options)
11
+ SORT_DIRECTIONS.each do |dir|
12
+ _sort_scope_name = :"#{sort_scope_name}_#{dir}"
13
+ has_scope(_sort_scope_name, only: only, type: type, **options)
14
+ end
15
+ end
16
+
17
+ def has_sort_scopes(*names, **options)
18
+ names.each{ |_name| has_sort_scope(_name, **options) }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -4,8 +4,10 @@ module Trax
4
4
  extend ::ActiveSupport::Autoload
5
5
 
6
6
  autoload :Base
7
+ autoload :NestedSearchScopes
7
8
  autoload :ResponseMeta
8
9
  autoload :Searchable
10
+ autoload :Sortable
9
11
  autoload :Pageable
10
12
  end
11
13
  end
@@ -2,7 +2,7 @@ module Trax
2
2
  module Controller
3
3
  class Engine < ::Rails::Engine
4
4
  initializer 'trax_controller.active_model_serializers' do |app|
5
- ::ActiveModel::Serializer.config.adapter = Trax::Controller::Serialization::Adapters::Json
5
+ ::ActiveModel::Serializer.config.adapter = ::Trax::Controller::Serialization::Adapters::Json
6
6
  end
7
7
  end
8
8
  end
@@ -0,0 +1,54 @@
1
+ module Trax
2
+ module Controller
3
+ module PermitParamsFor
4
+ extend ::ActiveSupport::Concern
5
+
6
+ # Allows you to permit params by creating a Trax::Core::Types::Struct
7
+ # https://github.com/jasonayre/trax_core/blob/master/lib/trax/core/types/struct.rb
8
+ # permitted_params_for_action :create do
9
+ # string :title
10
+ # end
11
+
12
+ included do
13
+ class_attribute :trax_params_permitters
14
+ self.trax_params_permitters = {}
15
+ end
16
+
17
+ def params_permitter_for_action
18
+ action = params[:action]
19
+ return self.trax_params_permitters[action.to_sym] if self.trax_params_permitters.key?(action.to_sym)
20
+ return self.trax_params_permitters[:save] if self.trax_params_permitters.key?(:save) && (action == 'create' || action == 'update' || action == 'first_or_create')
21
+ raise StandardError.new("No param permitter defined for action #{action}")
22
+ end
23
+
24
+ def build_resource_params
25
+ _params = request.parameters[resource_request_name]
26
+ self.class.trax_params_permitters[action_name.to_sym].new(_params).to_serializable_hash
27
+ end
28
+
29
+ def build_resource
30
+ get_resource_ivar || set_resource_ivar(end_of_association_chain.send(method_for_build, resource_params))
31
+ end
32
+
33
+ def update_resource(object, attributes)
34
+ object.update(attributes)
35
+ end
36
+
37
+ module ClassMethods
38
+ def permitted_params_for_action(action_name, &block)
39
+ _klass = ::Trax::Core::NamedClass.new("#{self.name}::PermittedParamsForAction#{action_name.to_s.classify}", Trax::Core::Types::Struct, &block)
40
+ self.trax_params_permitters[action_name] = _klass
41
+ end
42
+
43
+ def permitted_params_for_save(&block)
44
+ _update_klass = ::Trax::Core::NamedClass.new("#{self.name}::PermittedParamsForActionUpdate", Trax::Core::Types::Struct, &block)
45
+ _create_klass = ::Trax::Core::NamedClass.new("#{self.name}::PermittedParamsForActionCreate", Trax::Core::Types::Struct, &block)
46
+ _first_or_create_klass = ::Trax::Core::NamedClass.new("#{self.name}::PermittedParamsForActionFirstOrCreate", Trax::Core::Types::Struct, &block)
47
+ self.trax_params_permitters[:update] = _update_klass
48
+ self.trax_params_permitters[:create] = _create_klass
49
+ self.trax_params_permitters[:first_or_create] = _first_or_create_klass
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,60 +1,11 @@
1
- # This adapter is a workaround for
2
- # https://github.com/rails-api/active_model_serializers/issues/835 until
3
- # https://github.com/rails-api/active_model_serializers/pull/952 is merged
4
-
5
1
  module Trax
6
2
  module Controller
7
3
  module Serialization
8
4
  module Adapters
9
- class Json < ActiveModel::Serializer::Adapter::Json
10
- def serializable_hash(options={})
11
- result = is_collection? ? collection_serializable_hash(options) : resource_serializable_hash(options)
12
- @options[:nested] ? result : { root => result }
13
- end
14
-
15
- private
16
-
17
- def get_hash(serializer, options={})
18
- self.class.new(serializer, :nested => true).serializable_hash(options)
19
- end
20
-
21
- def collection_serializable_hash(options={})
22
- serializer.map { |s| get_hash(s, options) }
23
- end
24
-
25
- def is_collection?
26
- serializer.respond_to?(:each)
27
- end
28
-
29
- def resource_serializable_hash(options={})
30
- cached = cache_check(serializer){ serializer.attributes(options) }
31
- resource_result = serialize_resource_associations
32
- cached.merge(resource_result)
33
- end
34
-
35
- def serialize_resource_associations
36
- resource_result = {}
37
-
38
- serializer.associations.each do |association|
39
- association_serializer = association.serializer
40
- association_options = association.options
41
-
42
- if association_serializer.respond_to?(:each)
43
- array_serializer = association_serializer
44
-
45
- resource_result[association.key] = array_serializer.map do |item|
46
- cache_check(item) { get_hash(item) }
47
- end
48
- else
49
- resource_result[association.key] = if association_serializer && association_serializer.object
50
- cache_check(association_serializer) { get_hash(association_serializer) }
51
- elsif association_options[:virtual_value]
52
- association_options[:virtual_value]
53
- end
54
- end
55
- end
56
-
57
- resource_result
5
+ class Json < ::ActiveModelSerializers::Adapter::Json
6
+ def initialize(serializer, options = {})
7
+ super
8
+ options[:include] = "**"
58
9
  end
59
10
  end
60
11
  end
@@ -24,6 +24,7 @@ module Trax
24
24
  autoload :Resource
25
25
  autoload :InheritResources
26
26
  autoload :ActionTypes
27
+ autoload :PermitParamsFor
27
28
  autoload :Serialization
28
29
 
29
30
  @configuration ||= ::Trax::Controller::Config.new
@@ -1,3 +1,3 @@
1
1
  module TraxController
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.4"
3
3
  end
@@ -33,6 +33,10 @@ class CategoriesController < ::ApplicationController
33
33
  show(serializer: ::CategoriesSerializer, root: 'show_by_calling_original_action')
34
34
  end
35
35
 
36
+ def product_with_category
37
+ render_resource(serializer: ::ProductWithCategorySerializer, root: 'product', resource: Product.find(params[:id]))
38
+ end
39
+
36
40
  private
37
41
 
38
42
  def category_params
@@ -2,7 +2,7 @@ class CategorySerializer < ::ActiveModel::Serializer
2
2
  attributes :name, :slug
3
3
 
4
4
  def slug
5
- name.parameterize('-')
5
+ object.name.parameterize('-')
6
6
  end
7
7
 
8
8
  has_many :products, :serializer => ::ProductSerializer
@@ -0,0 +1,4 @@
1
+ class CategoryWithSubcategorySerializer < ::ActiveModel::Serializer
2
+ attributes :name
3
+ has_many :subcategories, :serializer => CategoryWithSubcategorySerializer
4
+ end
@@ -0,0 +1,6 @@
1
+ require "category_with_subcategories_serializer"
2
+
3
+ class ProductWithCategorySerializer < ::ActiveModel::Serializer
4
+ attributes :name
5
+ has_one :category, :serializer => CategoryWithSubcategorySerializer
6
+ end
@@ -13,6 +13,7 @@ Rails.application.routes.draw do
13
13
  get 'show_by_calling_original_action'
14
14
  get 'widget'
15
15
  get 'widget_with_renamed_root'
16
+ get 'product_with_category'
16
17
  end
17
18
  end
18
19
  end
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+
2
3
  describe ::Trax::Controller do
3
4
 
4
5
  end
@@ -2,11 +2,14 @@ require 'spec_helper'
2
2
 
3
3
  ::RSpec.describe CategoriesController, :type => :controller do
4
4
  before(:all) do
5
- @shoes_category = ::Category.create(:name => 'mens shoes')
6
- @watches_category = ::Category.create(:name => 'mens watches')
7
-
8
- @product1 = ::Product.create(:name => "DC Villan", :quantity => 0, :in_stock => false, :category => @shoes_category)
9
- @product2 = ::Product.create(:name => "Nixon Rotolog", :quantity => 2, :in_stock => true, :category => @watches_category)
5
+ @shoes_category = ::Category.create!(:name => 'mens shoes')
6
+ @watches_category = ::Category.create!(:name => 'mens watches')
7
+ @apparels_category = ::Category.create!(:name => 'mens apparels')
8
+ @shirts_category = @apparels_category.subcategories.create(:name => 'mens shirts')
9
+
10
+ @product1 = ::Product.create!(:name => "DC Villan", :quantity => 0, :in_stock => false, :category => @shoes_category)
11
+ @product2 = ::Product.create!(:name => "Nixon Rotolog", :quantity => 2, :in_stock => true, :category => @watches_category)
12
+ @product3 = ::Product.create!(:name => "T-Shirt", :quantity => 3, :in_stock => true, :category => @apparels_category)
10
13
  end
11
14
 
12
15
  context '#index' do
@@ -69,6 +72,24 @@ require 'spec_helper'
69
72
  expect(json["show_by_calling_original_action"]["name"]).to eq @shoes_category.name
70
73
  end
71
74
  end
75
+
76
+ describe "#product_with_category" do
77
+ it "deeply serializes" do
78
+ get :product_with_category, :id => @product3.id
79
+ json = ::JSON.parse(response.body)
80
+ expect(json["product"]).to eq(
81
+ "name" => @product3.name,
82
+ "category" => {
83
+ "name" => @apparels_category.name,
84
+ "subcategories" => [
85
+ { "name" => @shirts_category.name,
86
+ "subcategories" => []
87
+ }
88
+ ]
89
+ }
90
+ )
91
+ end
92
+ end
72
93
  end
73
94
 
74
95
  context '#create_with_modified_resource' do
@@ -1,15 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
- class NameCategorySerializer < ::ActiveModel::Serializer
4
- attributes :name
5
- has_many :subcategories, :serializer => NameCategorySerializer
6
- end
7
-
8
- class NameProductSerializer < ::ActiveModel::Serializer
9
- attributes :name
10
- has_one :category, :serializer => NameCategorySerializer
11
- end
12
-
13
3
  describe Trax::Controller::Serialization::Adapters::Json do
14
4
  let(:category_flat_heads){ ::Category.new(:name => "flat heads") }
15
5
  let(:category_screwdrivers){ ::Category.new(:name => "screwdrivers", :subcategories => [category_flat_heads]) }
@@ -17,7 +7,7 @@ describe Trax::Controller::Serialization::Adapters::Json do
17
7
  let(:category_tools){ ::Category.new(:name => "tools", :subcategories => [category_screwdrivers, category_knives]) }
18
8
  let(:product_tool){ ::Product.new(:name => "Generics Multi-Purpose Tool", :category => category_tools) }
19
9
  let(:root_key){ 'root_key' }
20
- let(:serializer){ ::NameProductSerializer.new(product_tool, :root => root_key) }
10
+ let(:serializer){ ::ProductWithCategorySerializer.new(product_tool, :root => root_key) }
21
11
  let!(:expected_root_key){ root_key.to_sym }
22
12
  let!(:expected_tool_hash){ {
23
13
  :name => product_tool.name,
@@ -40,7 +30,7 @@ describe Trax::Controller::Serialization::Adapters::Json do
40
30
  let(:category_cookware){ ::Category.new(:name => "cookware") }
41
31
  let(:product_pot){ ::Product.new(:name => "Pot", :category => category_cookware) }
42
32
  let(:collection){ [product_tool, product_pot] }
43
- let!(:expected_root_key){ root_key.pluralize.to_sym }
33
+ let(:root_key){ 'root_keys' }
44
34
  let!(:expected_pot_hash){ {
45
35
  :name => product_pot.name,
46
36
  :category => {
@@ -48,7 +38,7 @@ describe Trax::Controller::Serialization::Adapters::Json do
48
38
  :subcategories => []
49
39
  }
50
40
  }}
51
- let(:serializer){ ::ActiveModel::Serializer::ArraySerializer.new(collection, :root => root_key, :serializer => ::NameProductSerializer) }
41
+ let(:serializer){ ::ActiveModel::Serializer::CollectionSerializer.new(collection, :root => root_key, :serializer => ::ProductWithCategorySerializer) }
52
42
 
53
43
  it { expect(serialized).to eq(expected_root_key => [expected_tool_hash, expected_pot_hash]) }
54
44
  end
@@ -12,12 +12,14 @@ Gem::Specification.new do |spec|
12
12
  spec.description = %q{Resourceful, standardized controllers}
13
13
  spec.homepage = "http://www.github.com/jasonayre"
14
14
  spec.license = "MIT"
15
+ spec.required_ruby_version = '<= 3.0'
15
16
 
16
17
  spec.files = `git ls-files -z`.split("\x0")
17
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
20
  spec.require_paths = ["lib"]
20
21
 
22
+ spec.add_dependency "active_model_serializers", "~> 0.10"
21
23
  spec.add_dependency "trax_core"
22
24
  spec.add_dependency "will_paginate"
23
25
  spec.add_dependency "has_scope"
@@ -35,7 +37,8 @@ Gem::Specification.new do |spec|
35
37
  spec.add_development_dependency 'rspec-collection_matchers', '~> 1'
36
38
  spec.add_development_dependency 'guard', '~> 2'
37
39
  spec.add_development_dependency 'guard-bundler', '~> 2'
38
- spec.add_development_dependency 'rb-fsevent'
40
+ spec.add_development_dependency 'listen', '~> 3.0.3'
41
+ spec.add_development_dependency 'rb-fsevent', '~> 0.9.6'
39
42
  spec.add_development_dependency 'terminal-notifier-guard'
40
43
  spec.add_development_dependency 'pundit'
41
44
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trax_controller
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Ayre
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-22 00:00:00.000000000 Z
11
+ date: 2024-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: active_model_serializers
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.10'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.10'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: trax_core
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -248,20 +262,34 @@ dependencies:
248
262
  - - "~>"
249
263
  - !ruby/object:Gem::Version
250
264
  version: '2'
265
+ - !ruby/object:Gem::Dependency
266
+ name: listen
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - "~>"
270
+ - !ruby/object:Gem::Version
271
+ version: 3.0.3
272
+ type: :development
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - "~>"
277
+ - !ruby/object:Gem::Version
278
+ version: 3.0.3
251
279
  - !ruby/object:Gem::Dependency
252
280
  name: rb-fsevent
253
281
  requirement: !ruby/object:Gem::Requirement
254
282
  requirements:
255
- - - ">="
283
+ - - "~>"
256
284
  - !ruby/object:Gem::Version
257
- version: '0'
285
+ version: 0.9.6
258
286
  type: :development
259
287
  prerelease: false
260
288
  version_requirements: !ruby/object:Gem::Requirement
261
289
  requirements:
262
- - - ">="
290
+ - - "~>"
263
291
  - !ruby/object:Gem::Version
264
- version: '0'
292
+ version: 0.9.6
265
293
  - !ruby/object:Gem::Dependency
266
294
  name: terminal-notifier-guard
267
295
  requirement: !ruby/object:Gem::Requirement
@@ -327,12 +355,15 @@ files:
327
355
  - lib/trax/controller/authorize.rb
328
356
  - lib/trax/controller/collection.rb
329
357
  - lib/trax/controller/collection/base.rb
358
+ - lib/trax/controller/collection/nested_search_scopes.rb
330
359
  - lib/trax/controller/collection/pageable.rb
331
360
  - lib/trax/controller/collection/response_meta.rb
332
361
  - lib/trax/controller/collection/searchable.rb
362
+ - lib/trax/controller/collection/sortable.rb
333
363
  - lib/trax/controller/config.rb
334
364
  - lib/trax/controller/engine.rb
335
365
  - lib/trax/controller/inherit_resources.rb
366
+ - lib/trax/controller/permit_params_for.rb
336
367
  - lib/trax/controller/resource.rb
337
368
  - lib/trax/controller/resource/base.rb
338
369
  - lib/trax/controller/resource/response_meta.rb
@@ -352,7 +383,9 @@ files:
352
383
  - spec/internal/app/policies/widget_policy.rb
353
384
  - spec/internal/app/serializers/categories_serializer.rb
354
385
  - spec/internal/app/serializers/category_serializer.rb
386
+ - spec/internal/app/serializers/category_with_subcategories_serializer.rb
355
387
  - spec/internal/app/serializers/product_serializer.rb
388
+ - spec/internal/app/serializers/product_with_category_serializer.rb
356
389
  - spec/internal/app/serializers/widget_serializer.rb
357
390
  - spec/internal/config/database.yml
358
391
  - spec/internal/config/routes.rb
@@ -371,24 +404,23 @@ homepage: http://www.github.com/jasonayre
371
404
  licenses:
372
405
  - MIT
373
406
  metadata: {}
374
- post_install_message:
407
+ post_install_message:
375
408
  rdoc_options: []
376
409
  require_paths:
377
410
  - lib
378
411
  required_ruby_version: !ruby/object:Gem::Requirement
379
412
  requirements:
380
- - - ">="
413
+ - - "<="
381
414
  - !ruby/object:Gem::Version
382
- version: '0'
415
+ version: '3.0'
383
416
  required_rubygems_version: !ruby/object:Gem::Requirement
384
417
  requirements:
385
418
  - - ">="
386
419
  - !ruby/object:Gem::Version
387
420
  version: '0'
388
421
  requirements: []
389
- rubyforge_project:
390
- rubygems_version: 2.5.1
391
- signing_key:
422
+ rubygems_version: 3.5.9
423
+ signing_key:
392
424
  specification_version: 4
393
425
  summary: Resourceful, standardized controllers
394
426
  test_files:
@@ -403,7 +435,9 @@ test_files:
403
435
  - spec/internal/app/policies/widget_policy.rb
404
436
  - spec/internal/app/serializers/categories_serializer.rb
405
437
  - spec/internal/app/serializers/category_serializer.rb
438
+ - spec/internal/app/serializers/category_with_subcategories_serializer.rb
406
439
  - spec/internal/app/serializers/product_serializer.rb
440
+ - spec/internal/app/serializers/product_with_category_serializer.rb
407
441
  - spec/internal/app/serializers/widget_serializer.rb
408
442
  - spec/internal/config/database.yml
409
443
  - spec/internal/config/routes.rb