Working with Resources
What you'll learn
- How to create and manage resources in Plutonium
- Understanding resource definitions and configurations
- Working with fields, associations, and nested resources
- Implementing resource policies and scoping
- Best practices for resource organization
Introduction
Resources are the core building blocks of a Plutonium application. A resource represents a model in your application that can be managed through a consistent interface, complete with views, controllers, and policies.
Creating a Resource
The fastest way to create a resource is using the scaffold generator:
bash
rails generate pu:res:scaffold Blog user:belongs_to \
title:string content:text 'published_at:datetime?'
This generates several files, including:
ruby
class Blog < ResourceRecord
belongs_to :user
end
ruby
class BlogPolicy < Plutonium::Resource::Policy
def create?
true
end
def read?
true
end
def permitted_attributes_for_create
%i[user title content published_at]
end
def permitted_attributes_for_read
%i[user title content published_at]
end
end
ruby
class BlogDefinition < Plutonium::Resource::Definition
end
Resource Definitions
Resource definitions customize how a resource behaves in your application. They define:
- Fields and their types
- Available actions
- Search and filtering capabilities
- Sorting options
- Display configurations
Basic Field Configuration
ruby
class BlogDefinition < Plutonium::Resource::Definition
# Basic field definitions
field :content, as: :text
# Field with custom display options
field :published_at,
as: :datetime,
hint: "When this post should be published"
end
ruby
class BlogDefinition < Plutonium::Resource::Definition
# Customize how fields are displayed
display :title, class: "col-span-full"
display :content, class: "col-span-full" do |f|
f.text_tag class: "prose dark:prose-invert"
end
# Custom column display in tables
column :published_at, align: :end
end
Adding Custom Actions
Beyond CRUD, you can add custom actions to your resources:
ruby
# app/interactions/blogs/publish.rb
module Blogs
class Publish < Plutonium::Resource::Interaction
# Define what this interaction accepts
attribute :resource, class: Blog
attribute :publish_date, :date, default: -> { Time.current }
presents label: "Publish Blog",
icon: Phlex::TablerIcons::Send,
description: "Make this blog post public"
private
def execute
if resource.update(
published_at: publish_date
)
succeed(resource)
.with_message("Blog post published successfully")
.with_redirect_response(resource)
else
failed(resource.errors)
end
end
end
end
# app/definitions/blog_definition.rb
class BlogDefinition < Plutonium::Resource::Definition
# Register the custom action
action :publish,
interaction: Blogs::Publish,
category: :primary
end
Search and Filtering
Add search and filtering capabilities to your resources:
ruby
class BlogDefinition < Plutonium::Resource::Definition
# Enable full-text search
search do |scope, query|
scope.where("title ILIKE ? OR content ILIKE ?",
"%#{query}%", "%#{query}%")
end
# Add filters
filter :published_at,
with: DateFilter,
predicate: :gteq
# Add scopes
scope :published do |scope|
scope.where.not(published_at: nil)
end
scope :draft do |scope|
scope.where(published_at: nil)
end
# Configure sorting
sort :title
sort :published_at
end
Resource Policies
Policies control access to your resources:
ruby
class BlogPolicy < Plutonium::Resource::Policy
def permitted_attributes_for_create
%i[title content state published_at user_id]
end
def permitted_associations
%i[comments]
end
def create?
# Allow logged in users to create blogs
user.present?
end
def update?
# Users can only edit their own blogs
record.user_id == user.id
end
def publish?
# Only editors can publish
user.editor? && record.draft?
end
# Scope visible records
relation_scope do |relation|
relation = super(relation)
next relation unless user.admin?
relation.with_deleted
end
end
Best Practices
Resource Organization
- Keep resource definitions focused and cohesive
- Use packages to organize related resources
- Leverage policy scopes for authorization
- Extract complex logic into interactions
- Use presenters for view-specific logic
Common Pitfalls
- Avoid putting business logic in definitions
- Don't bypass policy checks
- Remember to scope resources appropriately
- Test your interactions and policies