Skip to content

Commit

Permalink
Feature/better error for missing resource (#2062)
Browse files Browse the repository at this point in the history
Co-authored-by: Adrian <[email protected]>
Co-authored-by: Paul Bob <[email protected]>
  • Loading branch information
3 people authored Dec 19, 2023
1 parent 636d1c6 commit f4813ed
Show file tree
Hide file tree
Showing 29 changed files with 362 additions and 65 deletions.
2 changes: 2 additions & 0 deletions app/controllers/avo/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ def detect_fields
end

def set_related_resource
raise Avo::MissingResourceError.new(related_resource_name) if related_resource.nil?

@related_resource = related_resource.new(params: params, view: action_name.to_sym, user: _current_user, record: @related_record).detect_fields
end

Expand Down
19 changes: 19 additions & 0 deletions db/factories.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,23 @@
status { "status" }
category { ::Product.categories.values.sample }
end

factory :location do
team { create :team }
name { Faker::Address.street_name }
address { Faker::Address.full_address }
size { ["small", "medium", "large"].sample }
end

factory :event do
location { create :location }
name { Faker::Lorem.sentence }
event_time { DateTime.now }
body { Faker::Lorem.paragraphs(number: rand(1...3)).join("\n") }
end

factory :store do
name { Faker::Company.name }
size { ["small", "medium", "large"].sample }
end
end
18 changes: 18 additions & 0 deletions lib/avo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,24 @@ class MissingGemError < StandardError; end

class DeprecatedAPIError < StandardError; end

class MissingResourceError < StandardError
def initialize(resource_name)
super(missing_resource_message(resource_name))
end

private

def missing_resource_message(resource_name)
name = resource_name.to_s.downcase

"Failed to find a resource while rendering the :#{name} field.\n" \
"You may generate a resource for it by running 'rails generate avo:resource #{name.singularize}'.\n" \
"\n" \
"Alternatively add the 'use_resource' option to the :#{name} field to specify a custom resource to be used.\n" \
"More info on https://docs.avohq.io/#{Avo::VERSION[0]}.0/resources.html."
end
end

class << self
attr_reader :logger
attr_reader :cache_store
Expand Down
6 changes: 6 additions & 0 deletions lib/avo/fields/base_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,12 @@ def on_create?
def in_action?
@action.present?
end

def get_resource_by_model_class(model_class)
resource = Avo.resource_manager.get_resource_by_model_class(model_class)

resource || (raise Avo::MissingResourceError.new(model_class))
end
end
end
end
6 changes: 3 additions & 3 deletions lib/avo/fields/belongs_to_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ def target_resource

if is_polymorphic?
if value.present?
return Avo.resource_manager.get_resource_by_model_class(value.class)
return get_resource_by_model_class(value.class)
else
return nil
end
Expand All @@ -243,9 +243,9 @@ def target_resource
reflection_key = polymorphic_as || id

if @record._reflections[reflection_key.to_s].klass.present?
Avo.resource_manager.get_resource_by_model_class @record._reflections[reflection_key.to_s].klass.to_s
get_resource_by_model_class(@record._reflections[reflection_key.to_s].klass.to_s)
elsif @record._reflections[reflection_key.to_s].options[:class_name].present?
Avo.resource_manager.get_resource_by_model_class @record._reflections[reflection_key.to_s].options[:class_name]
get_resource_by_model_class(@record._reflections[reflection_key.to_s].options[:class_name])
else
App.get_resource_by_name reflection_key.to_s
end
Expand Down
6 changes: 3 additions & 3 deletions lib/avo/fields/has_base_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def initialize(id, **args, &block)
end

def field_resource
resource || Avo.resource_manager.get_resource_by_model_class(@record.class)
resource || get_resource_by_model_class(@record.class)
end

def turbo_frame
Expand Down Expand Up @@ -57,9 +57,9 @@ def field_label

def target_resource
if @record._reflections[id.to_s].klass.present?
Avo.resource_manager.get_resource_by_model_class @record._reflections[id.to_s].klass.to_s
get_resource_by_model_class(@record._reflections[id.to_s].klass.to_s)
elsif @record._reflections[id.to_s].options[:class_name].present?
Avo.resource_manager.get_resource_by_model_class @record._reflections[id.to_s].options[:class_name]
get_resource_by_model_class(@record._reflections[id.to_s].options[:class_name])
else
Avo.resource_manager.get_resource_by_name id.to_s
end
Expand Down
5 changes: 5 additions & 0 deletions spec/dummy/app/avo/resources/course.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ def fields

field :links, as: :has_many, searchable: true, placeholder: "Click to choose a link",
discreet_pagination: true

if params[:show_location_field] == '1'
# Example for error message when resource is missing
field :locations, as: :has_and_belongs_to_many
end
end

def filters
Expand Down
15 changes: 15 additions & 0 deletions spec/dummy/app/avo/resources/event.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Avo::Resources::Event < Avo::BaseResource
self.title = :name
self.description = "An event that happened at a certain time."
self.includes = [:location]

def fields
field :name, as: :text, link_to_record: true, sortable: true, stacked: true
field :event_time, as: :datetime, sortable: true

if params[:show_location_field] == '1'
# Example for error message when resource is missing
field :location, as: :belongs_to
end
end
end
14 changes: 14 additions & 0 deletions spec/dummy/app/avo/resources/store.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Avo::Resources::Store < Avo::BaseResource
self.includes = [:location]

def fields
field :id, as: :id
field :name, as: :text
field :size, as: :text

if params[:show_location_field] == '1'
# Example for error message when resource is missing
field :location, as: :has_one
end
end
end
7 changes: 6 additions & 1 deletion spec/dummy/app/avo/resources/team.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class Avo::Resources::Team < Avo::BaseResource
self.includes = [:admin, :team_members]
self.includes = [:admin, :team_members, :locations]
self.search = {
query: -> { query.ransack(id_eq: params[:q], name_cont: params[:q], m: "or").result(distinct: false) }
}
Expand Down Expand Up @@ -79,6 +79,11 @@ def fields
field :admin, as: :has_one
field :team_members, as: :has_many, through: :memberships, translation_key: "avo.resource_translations.team_members"
field :reviews, as: :has_many

if params[:show_location_field] == '1'
# Example for error message when resource is missing
field :locations, as: :has_many
end
end

def filters
Expand Down
2 changes: 2 additions & 0 deletions spec/dummy/app/controllers/avo/events_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class Avo::EventsController < Avo::ResourcesController
end
2 changes: 2 additions & 0 deletions spec/dummy/app/controllers/avo/stores_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class Avo::StoresController < Avo::ResourcesController
end
3 changes: 1 addition & 2 deletions spec/dummy/app/models/city.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@
# features :json
# metadata :json
# image_url :string
# description :text
# status :string
# tiny_description :text
# created_at :datetime not null
# updated_at :datetime not null
# latitude :float
# longitude :float
# latitude :float
# city_center_area :json
#
class City < ApplicationRecord
Expand Down
2 changes: 2 additions & 0 deletions spec/dummy/app/models/course.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class Course < ApplicationRecord

has_many :links, -> { order(position: :asc) }, class_name: "Course::Link", inverse_of: :course

has_and_belongs_to_many :locations, inverse_of: :courses

validates :name, presence: true

def has_skills
Expand Down
14 changes: 9 additions & 5 deletions spec/dummy/app/models/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@
#
# Table name: events
#
# id :bigint not null, primary key
# name :string
# event_time :datetime
# created_at :datetime not null
# updated_at :datetime not null
# id :bigint not null, primary key
# name :string
# event_time :datetime
# created_at :datetime not null
# updated_at :datetime not null
# body :text
# location_id :bigint
#
class Event < ApplicationRecord
has_rich_text :body

belongs_to :location, optional: true
end
19 changes: 19 additions & 0 deletions spec/dummy/app/models/location.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# == Schema Information
#
# Table name: locations
#
# id :bigint not null, primary key
# team_id :bigint not null
# name :text
# address :string
# size :string
# created_at :datetime not null
# updated_at :datetime not null
# store_id :bigint
#
class Location < ApplicationRecord
belongs_to :store, optional: true
belongs_to :team, optional: true

has_and_belongs_to_many :courses, inverse_of: :locations
end
13 changes: 13 additions & 0 deletions spec/dummy/app/models/store.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# == Schema Information
#
# Table name: stores
#
# id :bigint not null, primary key
# name :string
# size :string
# created_at :datetime not null
# updated_at :datetime not null
#
class Store < ApplicationRecord
has_one :location
end
1 change: 1 addition & 0 deletions spec/dummy/app/models/team.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Team < ApplicationRecord

has_many :memberships, class_name: "TeamMembership"
has_many :team_members, through: :memberships, class_name: "User", source: :user, inverse_of: :teams
has_many :locations

has_one :admin_membership, -> { where level: :admin }, class_name: "TeamMembership", dependent: :destroy
has_one :admin, through: :admin_membership, source: :user, inverse_of: :teams
Expand Down
2 changes: 2 additions & 0 deletions spec/dummy/config/initializers/avo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,12 @@

section "Store", icon: "currency-dollar" do
resource :products
resource :stores
end

group "Other", collapsable: true, collapsed: true do
resource :fish, label: "Fishies"
resource :events
end
end

Expand Down
12 changes: 12 additions & 0 deletions spec/dummy/db/migrate/20231126035843_create_locations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class CreateLocations < ActiveRecord::Migration[6.1]
def change
create_table :locations do |t|
t.references :team, null: false, foreign_key: true
t.text :name
t.string :address
t.string :size

t.timestamps
end
end
end
10 changes: 10 additions & 0 deletions spec/dummy/db/migrate/20231205153910_create_courses_locations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class CreateCoursesLocations < ActiveRecord::Migration[6.1]
def change
create_table :courses_locations do |t|
t.references :user, null: false, foreign_key: true
t.references :course, null: false, foreign_key: true

t.timestamps
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddLocationToEvents < ActiveRecord::Migration[6.1]
def change
add_reference :events, :location, null: true, foreign_key: true
end
end
10 changes: 10 additions & 0 deletions spec/dummy/db/migrate/20231206112806_create_stores.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class CreateStores < ActiveRecord::Migration[6.1]
def change
create_table :stores do |t|
t.string :name
t.string :size

t.timestamps
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddStoreToLocations < ActiveRecord::Migration[6.1]
def change
add_reference :locations, :store, foreign_key: true
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class MakeTeamIdNullableOnLocations < ActiveRecord::Migration[6.1]
def change
change_column :locations, :team_id, :bigint, null: true
end
end
Loading

0 comments on commit f4813ed

Please sign in to comment.