Skip to content

Commit 1331d00

Browse files
committed
finishing touches
1 parent 2cbf4b3 commit 1331d00

5 files changed

Lines changed: 631 additions & 8 deletions

File tree

.formatter.exs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# Used by "mix format"
22
[
3-
43
import_deps: [:ecto],
54
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
65
]

LICENSE

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Copyright 2023 John Dengis
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4+
5+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6+
7+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 346 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1-
# EctoIrs
1+
# EctoIRS
22

3-
**TODO: Add description**
3+
[![Hex.pm](https://img.shields.io/hexpm/v/ecto_irs.svg)](https://hex.pm/packages/ecto_irs)
4+
[![Documentation](https://img.shields.io/badge/docs-hexdocs-blue.svg)](https://hexdocs.pm/ecto_irs)
5+
6+
EctoIRS is an Elixir library that provides easy auditing capabilities for Ecto schemas and migrations. The library allows developers to automatically track who created or modified database records.
7+
8+
## Features
9+
10+
- 🔍 **Automatic Audit Fields**: Automatically add `inserted_by` and `updated_by` fields to your schemas
11+
- 🗃️ **Migration Helpers**: Easy-to-use migration functions for adding audit columns
12+
- ⚙️ **Flexible Configuration**: Customize field names, references, and behavior
13+
- 🚀 **Auto-population**: Support for automatic field population via MFA tuples
14+
- 📦 **Zero Dependencies**: Built on top of Ecto with minimal external dependencies
415

516
## Installation
617

7-
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
8-
by adding `ecto_irs` to your list of dependencies in `mix.exs`:
18+
Add `ecto_irs` to your list of dependencies in `mix.exs`:
919

1020
```elixir
1121
def deps do
@@ -15,7 +25,336 @@ def deps do
1525
end
1626
```
1727

18-
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
19-
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
20-
be found at <https://hexdocs.pm/ecto_irs>.
28+
## Quick Start
29+
30+
### 1. Add Audit Columns to Your Database
31+
32+
In your migration:
33+
34+
```elixir
35+
defmodule MyApp.Repo.Migrations.CreatePosts do
36+
use Ecto.Migration
37+
import EctoIRS.Migration
38+
39+
def change do
40+
create table(:posts) do
41+
add :title, :string
42+
add :content, :text
43+
44+
# Adds :inserted_by_id and :updated_by_id columns
45+
audits :users
46+
47+
timestamps()
48+
end
49+
end
50+
end
51+
```
52+
53+
### 2. Add Audit Fields to Your Schema
54+
55+
In your schema:
56+
57+
```elixir
58+
defmodule MyApp.Post do
59+
use Ecto.Schema
60+
use EctoIRS.Schema
61+
62+
schema "posts" do
63+
field :title, :string
64+
field :content, :text
65+
66+
# Generates :inserted_by and :updated_by associations
67+
audits MyApp.User
68+
69+
timestamps()
70+
end
71+
end
72+
```
73+
74+
### 3. Query with Audit Information
75+
76+
```elixir
77+
# Preload audit associations
78+
post = MyApp.Repo.get(MyApp.Post, 1) |> MyApp.Repo.preload([:inserted_by, :updated_by])
79+
80+
# Access audit information
81+
IO.puts "Created by: #{post.inserted_by.name}"
82+
IO.puts "Last updated by: #{post.updated_by.name}"
83+
```
84+
85+
## Schema Usage
86+
87+
### Basic Usage
88+
89+
```elixir
90+
defmodule MyApp.Post do
91+
use Ecto.Schema
92+
use EctoIRS.Schema
93+
94+
schema "posts" do
95+
field :title, :string
96+
audits MyApp.User
97+
timestamps()
98+
end
99+
end
100+
```
101+
102+
### Custom Field Names
103+
104+
```elixir
105+
defmodule MyApp.Post do
106+
use Ecto.Schema
107+
use EctoIRS.Schema
108+
109+
schema "posts" do
110+
field :title, :string
111+
112+
audits MyApp.User,
113+
inserted_by: :created_by,
114+
updated_by: :modified_by
115+
end
116+
end
117+
```
118+
119+
### Disable Specific Fields
120+
121+
```elixir
122+
defmodule MyApp.Post do
123+
use Ecto.Schema
124+
use EctoIRS.Schema
125+
126+
schema "posts" do
127+
field :title, :string
128+
129+
# Only track who created, not who updated
130+
audits MyApp.User, updated_by: false
131+
end
132+
end
133+
```
134+
135+
### Custom References
136+
137+
```elixir
138+
defmodule MyApp.Post do
139+
use Ecto.Schema
140+
use EctoIRS.Schema
141+
142+
schema "posts" do
143+
field :title, :string
144+
145+
audits MyApp.User, references: :user_id
146+
end
147+
end
148+
```
149+
150+
### Automatic Field Population
151+
152+
```elixir
153+
defmodule MyApp.Post do
154+
use Ecto.Schema
155+
use EctoIRS.Schema
156+
157+
schema "posts" do
158+
field :title, :string
159+
160+
audits MyApp.User, autogenerate: {MyApp.Context, :current_user_id, []}
161+
end
162+
end
163+
```
164+
165+
### Pre-configuration
166+
167+
```elixir
168+
defmodule MyApp.Post do
169+
use Ecto.Schema
170+
use EctoIRS.Schema
171+
172+
@audits_opts [autogenerate: {MyApp.Context, :current_user_id, []}]
173+
174+
schema "posts" do
175+
field :title, :string
176+
audits MyApp.User
177+
end
178+
end
179+
```
180+
181+
## Migration Usage
182+
183+
### Basic Migration
184+
185+
```elixir
186+
defmodule MyApp.Repo.Migrations.CreatePosts do
187+
use Ecto.Migration
188+
import EctoIRS.Migration
189+
190+
def change do
191+
create table(:posts) do
192+
add :title, :string
193+
audits :users
194+
timestamps()
195+
end
196+
end
197+
end
198+
```
199+
200+
### Custom Column Names
201+
202+
```elixir
203+
defmodule MyApp.Repo.Migrations.CreatePosts do
204+
use Ecto.Migration
205+
import EctoIRS.Migration
206+
207+
def change do
208+
create table(:posts) do
209+
add :title, :string
210+
211+
audits :users,
212+
inserted_by: :created_by,
213+
updated_by: :modified_by
214+
215+
timestamps()
216+
end
217+
end
218+
end
219+
```
220+
221+
### Nullable Columns
222+
223+
```elixir
224+
defmodule MyApp.Repo.Migrations.CreatePosts do
225+
use Ecto.Migration
226+
import EctoIRS.Migration
227+
228+
def change do
229+
create table(:posts) do
230+
add :title, :string
231+
audits :users, null: true
232+
timestamps()
233+
end
234+
end
235+
end
236+
```
237+
238+
### Adding to Existing Tables
239+
240+
```elixir
241+
defmodule MyApp.Repo.Migrations.AddAuditsToExistingTable do
242+
use Ecto.Migration
243+
import EctoIRS.Migration
244+
245+
def change do
246+
alter table(:existing_posts) do
247+
audits :users
248+
end
249+
end
250+
end
251+
```
252+
253+
### Custom Reference Options
254+
255+
```elixir
256+
defmodule MyApp.Repo.Migrations.CreatePosts do
257+
use Ecto.Migration
258+
import EctoIRS.Migration
259+
260+
def change do
261+
create table(:posts) do
262+
add :title, :string
263+
264+
audits :users,
265+
column: :user_id,
266+
on_delete: :nilify_all,
267+
on_update: :update_all
268+
269+
timestamps()
270+
end
271+
end
272+
end
273+
```
274+
275+
## Configuration
276+
277+
### Repository Configuration
278+
279+
Configure default audit options at the repository level:
280+
281+
```elixir
282+
config :my_app, MyApp.Repo,
283+
migration_audits: [
284+
inserted_by: :created_by,
285+
updated_by: :modified_by,
286+
null: false
287+
]
288+
```
289+
290+
### Schema Configuration Options
291+
292+
- `inserted_by`: The field name for insertion audit (default: `:inserted_by`)
293+
- `updated_by`: The field name for update audit (default: `:updated_by`)
294+
- `references`: The field on the referenced table (default: `:id`)
295+
- `autogenerate`: MFA tuple for automatic field population
296+
297+
### Migration Configuration Options
298+
299+
- `inserted_by`: Column name prefix for insertion audit (default: `:inserted_by`)
300+
- `updated_by`: Column name prefix for update audit (default: `:updated_by`)
301+
- `null`: Whether columns accept null values (default: `false`)
302+
303+
## Best Practices
304+
305+
### 1. Add Indexes for Performance
306+
307+
```elixir
308+
create index(:posts, [:inserted_by_id])
309+
create index(:posts, [:updated_by_id])
310+
```
311+
312+
### 2. Use Consistent Naming
313+
314+
Stick to either the default names or establish a consistent naming convention across your application.
315+
316+
### 3. Consider Nullable Columns
317+
318+
Decide whether audit fields should be required based on your application's security requirements.
319+
320+
### 4. Preload Associations
321+
322+
Always preload audit associations when you need to access the audit information:
323+
324+
```elixir
325+
posts = MyApp.Repo.all(MyApp.Post) |> MyApp.Repo.preload([:inserted_by, :updated_by])
326+
```
327+
328+
## Development
329+
330+
### Running Tests
331+
332+
```bash
333+
mix test
334+
```
335+
336+
### Code Quality
337+
338+
```bash
339+
mix credo # Run static code analysis
340+
mix dialyzer # Run type checking
341+
```
342+
343+
### Documentation
344+
345+
```bash
346+
mix docs # Generate documentation
347+
```
348+
349+
## Contributing
350+
351+
1. Fork the repository
352+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
353+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
354+
4. Push to the branch (`git push origin feature/amazing-feature`)
355+
5. Open a Pull Request
356+
357+
## License
358+
359+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
21360

0 commit comments

Comments
 (0)