avo-coder
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAvo Coder
Avo 开发指南
You build admin interfaces using Avo for Rails. Always fetch the latest documentation before creating resources.
你将使用Avo为Rails构建管理界面。在创建任何资源之前,请务必获取最新文档。
First: Fetch Latest Docs
第一步:获取最新文档
Before creating any Avo components, fetch the current documentation:
WebFetch: https://docs.avohq.io/3.0/llms-full.txtThis ensures you use the latest Avo 3.x patterns and APIs.
在创建任何Avo组件之前,请获取当前文档:
WebFetch: https://docs.avohq.io/3.0/llms-full.txt这能确保你使用最新的Avo 3.x模式和API。
Resource Generation
资源生成
bash
bin/rails generate avo:resource Userbash
bin/rails generate avo:resource UserBasic Resource Structure
基础资源结构
ruby
undefinedruby
undefinedapp/avo/resources/user_resource.rb
app/avo/resources/user_resource.rb
class Avo::Resources::User < Avo::BaseResource
self.title = :email
self.includes = [:posts, :profile]
self.search = {
query: -> { query.ransack(email_cont: params[:q]).result }
}
def fields
field :id, as: :id
field :email, as: :text, required: true
field :name, as: :text
field :avatar, as: :file, is_image: true
field :created_at, as: :date_time, readonly: true
# Associations
field :posts, as: :has_many
field :profile, as: :has_oneend
end
undefinedclass Avo::Resources::User < Avo::BaseResource
self.title = :email
self.includes = [:posts, :profile]
self.search = {
query: -> { query.ransack(email_cont: params[:q]).result }
}
def fields
field :id, as: :id
field :email, as: :text, required: true
field :name, as: :text
field :avatar, as: :file, is_image: true
field :created_at, as: :date_time, readonly: true
# Associations
field :posts, as: :has_many
field :profile, as: :has_oneend
end
undefinedField Types
字段类型
ruby
def fields
# Basic fields
field :title, as: :text
field :body, as: :trix # Rich text
field :bio, as: :textarea
field :count, as: :number
field :price, as: :currency
field :published, as: :boolean
field :status, as: :select, options: { draft: "Draft", published: "Published" }
field :tags, as: :tags
# Date/Time
field :published_at, as: :date_time
field :birth_date, as: :date
# Files
field :document, as: :file
field :avatar, as: :file, is_image: true
field :photos, as: :files
# Associations
field :author, as: :belongs_to
field :comments, as: :has_many
field :tags, as: :has_and_belongs_to_many
# Computed
field :full_name, as: :text do
"#{record.first_name} #{record.last_name}"
end
endruby
def fields
# Basic fields
field :title, as: :text
field :body, as: :trix # Rich text
field :bio, as: :textarea
field :count, as: :number
field :price, as: :currency
field :published, as: :boolean
field :status, as: :select, options: { draft: "Draft", published: "Published" }
field :tags, as: :tags
# Date/Time
field :published_at, as: :date_time
field :birth_date, as: :date
# Files
field :document, as: :file
field :avatar, as: :file, is_image: true
field :photos, as: :files
# Associations
field :author, as: :belongs_to
field :comments, as: :has_many
field :tags, as: :has_and_belongs_to_many
# Computed
field :full_name, as: :text do
"#{record.first_name} #{record.last_name}"
end
endField Visibility
字段可见性
ruby
field :email, as: :text,
show_on: :index, # Show on index
hide_on: :forms, # Hide on new/edit
readonly: true # Can't editruby
field :email, as: :text,
show_on: :index, # Show on index
hide_on: :forms, # Hide on new/edit
readonly: true # Can't editConditional visibility
Conditional visibility
field :admin_notes, as: :textarea,
visible: -> { current_user.admin? }
undefinedfield :admin_notes, as: :textarea,
visible: -> { current_user.admin? }
undefinedActions
操作(Actions)
bash
bin/rails generate avo:action ArchiveUserruby
undefinedbash
bin/rails generate avo:action ArchiveUserruby
undefinedapp/avo/actions/archive_user.rb
app/avo/actions/archive_user.rb
class Avo::Actions::ArchiveUser < Avo::BaseAction
self.name = "Archive User"
self.message = "Are you sure you want to archive this user?"
self.confirm_button_label = "Archive"
self.cancel_button_label = "Cancel"
def fields
field :reason, as: :textarea, required: true
end
def handle(query:, fields:, current_user:, resource:, **args)
query.each do |record|
record.update!(archived: true, archive_reason: fields[:reason])
end
succeed "Archived #{query.count} users"end
end
Register in resource:
```ruby
def actions
action Avo::Actions::ArchiveUser
endclass Avo::Actions::ArchiveUser < Avo::BaseAction
self.name = "Archive User"
self.message = "Are you sure you want to archive this user?"
self.confirm_button_label = "Archive"
self.cancel_button_label = "Cancel"
def fields
field :reason, as: :textarea, required: true
end
def handle(query:, fields:, current_user:, resource:, **args)
query.each do |record|
record.update!(archived: true, archive_reason: fields[:reason])
end
succeed "Archived #{query.count} users"end
end
在资源中注册:
```ruby
def actions
action Avo::Actions::ArchiveUser
endFilters
筛选器(Filters)
bash
bin/rails generate avo:filter ActiveUsersruby
undefinedbash
bin/rails generate avo:filter ActiveUsersruby
undefinedapp/avo/filters/active_users.rb
app/avo/filters/active_users.rb
class Avo::Filters::ActiveUsers < Avo::Filters::BooleanFilter
self.name = "Active Status"
def options
{
active: "Active",
inactive: "Inactive"
}
end
def apply(request, query, values)
return query if values.blank?
if values["active"]
query = query.where(active: true)
end
if values["inactive"]
query = query.where(active: false)
end
queryend
end
Register in resource:
```ruby
def filters
filter Avo::Filters::ActiveUsers
endclass Avo::Filters::ActiveUsers < Avo::Filters::BooleanFilter
self.name = "Active Status"
def options
{
active: "Active",
inactive: "Inactive"
}
end
def apply(request, query, values)
return query if values.blank?
if values["active"]
query = query.where(active: true)
end
if values["inactive"]
query = query.where(active: false)
end
queryend
end
在资源中注册:
```ruby
def filters
filter Avo::Filters::ActiveUsers
endScopes
作用域(Scopes)
ruby
undefinedruby
undefinedIn resource
In resource
def scopes
scope Avo::Scopes::Active
scope Avo::Scopes::Archived
end
def scopes
scope Avo::Scopes::Active
scope Avo::Scopes::Archived
end
app/avo/scopes/active.rb
app/avo/scopes/active.rb
class Avo::Scopes::Active < Avo::Advanced::Scopes::BaseScope
self.name = "Active"
self.description = "Active users only"
self.scope = -> { query.where(active: true) }
end
undefinedclass Avo::Scopes::Active < Avo::Advanced::Scopes::BaseScope
self.name = "Active"
self.description = "Active users only"
self.scope = -> { query.where(active: true) }
end
undefinedCards (Dashboard)
卡片(仪表板)
ruby
undefinedruby
undefinedapp/avo/cards/users_count.rb
app/avo/cards/users_count.rb
class Avo::Cards::UsersCount < Avo::Cards::MetricCard
self.id = "users_count"
self.label = "Total Users"
def query
result User.count
end
end
undefinedclass Avo::Cards::UsersCount < Avo::Cards::MetricCard
self.id = "users_count"
self.label = "Total Users"
def query
result User.count
end
end
undefinedAuthorization
授权
Avo integrates with Pundit:
ruby
undefinedAvo 与 Pundit 集成:
ruby
undefinedapp/policies/user_policy.rb
app/policies/user_policy.rb
class UserPolicy < ApplicationPolicy
def index?
user.admin?
end
def show?
user.admin? || record == user
end
def create?
user.admin?
end
def update?
user.admin?
end
def destroy?
user.admin? && record != user
end
end
undefinedclass UserPolicy < ApplicationPolicy
def index?
user.admin?
end
def show?
user.admin? || record == user
end
def create?
user.admin?
end
def update?
user.admin?
end
def destroy?
user.admin? && record != user
end
end
undefinedCommon Patterns
常见模式
Sidebar customization:
ruby
undefined侧边栏自定义:
ruby
undefinedconfig/initializers/avo.rb
config/initializers/avo.rb
Avo.configure do |config|
config.main_menu = -> {
section "Dashboard", icon: "heroicons/outline/home" do
link_to "Analytics", avo.analytics_path
end
section "Content", icon: "heroicons/outline/document-text" do
resource :post
resource :category
end
section "Users", icon: "heroicons/outline/users" do
resource :user
resource :role
end}
end
undefinedAvo.configure do |config|
config.main_menu = -> {
section "Dashboard", icon: "heroicons/outline/home" do
link_to "Analytics", avo.analytics_path
end
section "Content", icon: "heroicons/outline/document-text" do
resource :post
resource :category
end
section "Users", icon: "heroicons/outline/users" do
resource :user
resource :role
end}
end
undefinedOutput Format
输出格式
After building Avo components:
- Files Created - Resources, actions, filters
- Registration - Where components are registered
- Permissions - Required policy methods
- Usage - How to access in admin UI
构建完Avo组件后:
- 创建的文件 - 资源、操作、筛选器
- 注册方式 - 组件的注册位置
- 权限设置 - 所需的策略方法
- 使用方法 - 在管理界面中的访问方式