Class: RailsConsoleAi::Skill
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- RailsConsoleAi::Skill
- Defined in:
- app/models/rails_console_ai/skill.rb
Constant Summary collapse
- STATUS_PROPOSED =
'proposed'.freeze
- STATUS_APPROVED =
'approved'.freeze
- STATUSES =
[STATUS_PROPOSED, STATUS_APPROVED].freeze
Class Method Summary collapse
- .connection ⇒ Object
-
.record_use!(id) ⇒ Object
Atomically bump use_count + last_used_at without firing callbacks / validations / updated_at.
Instance Method Summary collapse
- #approve!(approved_by:) ⇒ Object
- #approved? ⇒ Boolean
- #body ⇒ Object
- #bypass_guards_for_methods ⇒ Object
- #content=(value) ⇒ Object
- #description ⇒ Object
-
#parsed ⇒ Object
Parsed view of the raw markdown content.
- #proposed? ⇒ Boolean
- #tags ⇒ Object
- #to_hash ⇒ Object
-
#update_with_version!(attrs, edited_by: nil, change_note: nil, preserve_approval: false) ⇒ Object
Assigns attrs, saves, and records one SkillVersion snapshot.
Class Method Details
.connection ⇒ Object
28 29 30 31 32 33 34 35 36 |
# File 'app/models/rails_console_ai/skill.rb', line 28 def self.connection klass = RailsConsoleAi.configuration.connection_class if klass klass = Object.const_get(klass) if klass.is_a?(String) klass.connection else super end end |
.record_use!(id) ⇒ Object
Atomically bump use_count + last_used_at without firing callbacks / validations / updated_at. Safe to call from concurrent AI tool calls.
59 60 61 62 63 64 65 66 67 68 |
# File 'app/models/rails_console_ai/skill.rb', line 59 def self.record_use!(id) where(id: id).update_all([ 'use_count = COALESCE(use_count, 0) + 1, last_used_at = ?', Time.now.utc ]) true rescue ::ActiveRecord::ActiveRecordError => e RailsConsoleAi.logger.warn("RailsConsoleAi::Skill.record_use!(#{id.inspect}) failed: #{e.}") false end |
Instance Method Details
#approve!(approved_by:) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'app/models/rails_console_ai/skill.rb', line 115 def approve!(approved_by:) raise ArgumentError, 'approved_by is required' if approved_by.to_s.strip.empty? update_with_version!( { status: STATUS_APPROVED, approved_by: approved_by, approved_at: Time.now.utc }, edited_by: approved_by, change_note: "Approved by #{approved_by}", preserve_approval: true ) end |
#approved? ⇒ Boolean
55 |
# File 'app/models/rails_console_ai/skill.rb', line 55 def approved?; status.to_s == STATUS_APPROVED; end |
#body ⇒ Object
50 |
# File 'app/models/rails_console_ai/skill.rb', line 50 def body; parsed['body']; end |
#bypass_guards_for_methods ⇒ Object
52 |
# File 'app/models/rails_console_ai/skill.rb', line 52 def bypass_guards_for_methods; Array(parsed['bypass_guards_for_methods']); end |
#content=(value) ⇒ Object
44 45 46 47 |
# File 'app/models/rails_console_ai/skill.rb', line 44 def content=(value) @parsed = nil super end |
#description ⇒ Object
49 |
# File 'app/models/rails_console_ai/skill.rb', line 49 def description; parsed['description']; end |
#parsed ⇒ Object
Parsed view of the raw markdown content. Memoized per-instance and cleared on assignment. Returns {} for invalid content so callers don’t need to nil-guard.
40 41 42 |
# File 'app/models/rails_console_ai/skill.rb', line 40 def parsed @parsed ||= (RailsConsoleAi::SkillLoader.parse(content.to_s) || {}) end |
#proposed? ⇒ Boolean
54 |
# File 'app/models/rails_console_ai/skill.rb', line 54 def proposed?; status.to_s == STATUS_PROPOSED; end |
#tags ⇒ Object
51 |
# File 'app/models/rails_console_ai/skill.rb', line 51 def ; Array(parsed['tags']); end |
#to_hash ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'app/models/rails_console_ai/skill.rb', line 70 def to_hash { 'id' => id, 'name' => name, 'description' => description, 'body' => body, 'tags' => , 'bypass_guards_for_methods' => bypass_guards_for_methods, 'content' => content, 'status' => status, 'approved_by' => approved_by, 'approved_at' => approved_at, 'use_count' => use_count, 'last_used_at' => last_used_at, 'source' => :db, 'updated_at' => updated_at } end |
#update_with_version!(attrs, edited_by: nil, change_note: nil, preserve_approval: false) ⇒ Object
Assigns attrs, saves, and records one SkillVersion snapshot. Any change to ‘content` reverts approval back to “proposed” unless `preserve_approval: true` is passed (approve! does this).
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'app/models/rails_console_ai/skill.rb', line 92 def update_with_version!(attrs, edited_by: nil, change_note: nil, preserve_approval: false) transaction do assign_attributes(attrs) if !preserve_approval && approved? && changes.key?('content') self.status = STATUS_PROPOSED self.approved_by = nil self.approved_at = nil end save! RailsConsoleAi::SkillVersion.create!( skill_id: id, name: name, content: content, status: status, edited_by: edited_by, change_note: change_note ) end self end |