一键导入
grant-crud-operations
Create, read, update, and delete operations in Grant ORM including bulk operations, batch processing, upserts, and convenience methods.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Create, read, update, and delete operations in Grant ORM including bulk operations, batch processing, upserts, and convenience methods.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Grant ORM advanced features including enum attributes, dirty tracking, serialized columns, value objects, horizontal sharding, and async operations.
Grant ORM associations including belongs_to, has_one, has_many, has_many through, polymorphic, dependent options, counter_cache, eager loading, and nested attributes.
Grant ORM lifecycle callbacks, transaction blocks, nested transactions with savepoints, isolation levels, optimistic and pessimistic locking.
Generate a new Grant ORM model file with proper structure, column definitions, validations, associations, and callbacks.
Defining Grant ORM models with columns, types, primary keys, timestamps, connections, converters, and serialization.
Grant ORM query builder API including where clauses, operators, WhereChain, OR/NOT groups, scopes, aggregations, raw SQL, and Enumerable integration.
| name | grant-crud-operations |
| description | Create, read, update, and delete operations in Grant ORM including bulk operations, batch processing, upserts, and convenience methods. |
| user-invocable | false |
# Create and save in one step
post = Post.create(title: "Grant ORM Guide", content: "Learn Grant", published: true)
post.persisted? # => true if saved successfully
# Create with exception on failure
post = Post.create!(title: "Grant ORM Guide") # Raises Grant::RecordNotSaved on failure
# New + save
post = Post.new
post.title = "My Post"
post.save # => true/false
post.save! # Raises on failure
# New with named args
post = Post.new(title: "My Post", content: "Content", author_id: 1)
post.save
# New with block
post = Post.new do |p|
p.title = "Another Post"
p.content = "More content"
end
post.save!
Post.create({title: "No Timestamps"}, skip_timestamps: true)
post.save(validate: false) # Skip validation
post.save(skip_callbacks: true) # Skip callbacks
# insert_all -- single SQL INSERT, no validations/callbacks
User.insert_all([
{name: "Alice", email: "alice@example.com"},
{name: "Bob", email: "bob@example.com"}
])
# With timestamps
User.insert_all(data, record_timestamps: true)
# With RETURNING (PostgreSQL/SQLite 3.35+)
created = User.insert_all(data, returning: [:id, :name, :email])
user = User.find(1) # => User? (nil if not found)
user = User.find!(1) # Raises Grant::RecordNotFound
users = User.find([1, 2, 3]) # Array of found records
user = User.find_by(email: "john@example.com")
user = User.find_by!(email: "john@example.com") # Raises if not found
post = Post.find_by(author_id: 1, published: true, category: "tech")
user = User.find_or_create_by(email: "new@example.com") do |u|
u.name = "New User"
end
user = User.find_or_initialize_by(email: "test@example.com")
user.new_record? # => true if not found
User.first # => User?
User.first! # Raises if empty
User.first(5) # First 5 records
User.last # => User?
User.last! # Raises if empty
User.last(10) # Last 10 records
User.all # All records (iterable)
User.any? # => true if any records
User.none? # => true if no records
User.exists?(1) # By ID
User.exists?(email: "test@example.com") # By attributes
User.where(published: true).exists? # With query builder
Find exactly one record (raises if zero or multiple match):
admin = User.where(role: "admin").sole
user = User.find_sole_by(email: "john@example.com")
# Raises Grant::Querying::NotFound or Grant::Querying::NotUnique
user = User.find(1)
user.name = "Changed"
user.reload # Discards unsaved changes, re-fetches from DB
user.name # => Original name
# Extract column values without instantiating models
names = User.pluck(:name) # => [["Alice"], ["Bob"]]
data = User.pluck(:id, :name, :email) # => [[1, "Alice", "alice@..."], ...]
# Pick first result only
first_name = User.pick(:name) # => "Alice"
first_data = User.where(active: true).pick(:id, :name) # => [1, "Alice"]
users = User.select(:id, :name, :email)
user = User.find(1)
user.name = "Updated Name"
user.save
user.update(name: "New Name", email: "new@example.com")
user.update!(name: "Must Work") # Raises on failure
# Skip validation
user.update_attribute(:last_login, Time.utc)
# Direct SQL, skips callbacks/validation
user.update_columns(name: "Direct Update", updated_at: Time.utc)
User.where(active: false).update_all(status: "inactive", deactivated_at: Time.utc)
Post.where(published: true).update_all("view_count = view_count + 1")
post.increment(:view_count) # +1 (does not save)
post.increment(:view_count, 5) # +5
post.increment!(:view_count) # +1 and save
post.decrement!(:stock_quantity, 10)
user.toggle(:active) # true <-> false
user.toggle!(:email_verified) # Toggle and save
post.touch # Updates updated_at
post.touch(:published_at) # Updates specific timestamp
comment.touch(include_parent: true) # Also touches parent
User.where(active: true).touch_all # Touch all matching
User.upsert(
{email: "john@example.com", name: "John Doe", age: 30},
unique_by: [:email]
)
User.upsert_all([
{email: "alice@example.com", name: "Alice"},
{email: "bob@example.com", name: "Bob"}
], unique_by: [:email])
Product.upsert_all(data, unique_by: [:sku], update_only: [:price, :stock])
Post.update_counters(post_id, {:views => 1, :comments_count => 2, :shares => -1})
user.destroy # => true/false (runs callbacks)
user.destroy! # Raises if fails
user.destroyed? # => true
User.delete(1) # By ID, skips callbacks
User.delete([1, 2, 3]) # Multiple IDs
User.where(active: false).delete_all # Skips callbacks
User.where(spam: true).destroy_all # Runs callbacks
Post.clear # Truncate table
User.destroy_by(active: false) # Find and destroy all matching
User.delete_by(spam: true) # Find and delete (no callbacks)
User.delete_by(role: "guest", last_login: ..1.year.ago)
# Process records in batches (avoids loading all into memory)
User.find_in_batches(batch_size: 1000) do |users|
users.each { |user| process(user) }
end
# With query methods available on batch
User.in_batches(of: 1000) do |batch|
batch.update_all(processed: true)
end
# With start/finish constraints
User.in_batches(of: 500, start: 1000, finish: 5000) do |batch|
# Process IDs 1000-5000
end
begin
user = User.create!(invalid_data)
rescue Grant::RecordInvalid => e
puts "Validation failed: #{e.record.errors.full_messages}"
rescue Grant::RecordNotFound => e
puts "Record not found: #{e.message}"
rescue Grant::RecordNotSaved => e
puts "Save failed: #{e.record.errors.full_messages}"
rescue Grant::RecordNotDestroyed => e
puts "Destroy failed: #{e.record.errors.full_messages}"
end