ai_refactor 0.4.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 725fb1da5fc311d3740687d97fa3b6c3c4292a3b531f467ea1d8ff9e734608bc
4
- data.tar.gz: 4c16d310c643ae1158442816a9f863961ae151bb4ae486c965e96340342e2d44
3
+ metadata.gz: e50d610e50fdbccc133cd5951cee61244602b402917aa2eb1ab37713b3a6b276
4
+ data.tar.gz: eee461b016a3dec20476828383da3571999649097472eedc68f736d6ea759057
5
5
  SHA512:
6
- metadata.gz: d0f380ef54a29be017b23c2caaa4491ee6304dc410e52ab6e11038b9f30c30a09a04597f3342332f464007e0e932f5b81112f712d46c584b2728d51bee61c036
7
- data.tar.gz: 9ffa29857815cb73daef7d6902bf7301dc80e36361b0451d3d3df1b7921b1c0978ef16ea7963c544b893db1bd0d6db34120378aa6a7ae4ac5add0831e4b61dbf
6
+ metadata.gz: c4c913a3263949687e98681697e5fe2631748aa57dbc3ea4c7aa3f367a3ce98cb6d2d3ea86653f2e949fd65d055dd9c0f67d93c79602742fb179a27568639ed6
7
+ data.tar.gz: 41324b5dd54d62f59d749638c7b813e4d2fcc4d75528aaf4e37ba4027773b87195a1dad6ffc4400b9ce34ba38004319d7385879b8d01f00a8161a86eec842a6a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # AI Refactor Changelog
2
2
 
3
+ ## [0.5.1] - 2023-09-21
4
+
5
+ ### Added
6
+
7
+ - Support for substitutions in path templates.
8
+
9
+ ### Fixed
10
+
11
+ - Fixes issue with refactor type specified on command line not being picked up.
12
+
13
+
14
+ ## [0.5.0] - 2023-09-21
15
+
16
+ ### Added
17
+
18
+ - Support for new command files, which are YAML files that can be used to define options for a refactor. This makes it
19
+ simpler to create configurations for refactors that will be used repeatedly. They can be committed to source control
20
+ of your project and shared with other developers.
21
+ - Support for configuring the run commands for the test runners
22
+ - Adding real life examples
23
+
3
24
  ## [0.4.0] - 2023-08-15
4
25
 
5
26
  ### Added
data/Gemfile CHANGED
@@ -12,3 +12,10 @@ gem "minitest", "~> 5.0"
12
12
  gem "standard", "~> 1.3"
13
13
 
14
14
  gem "dotenv"
15
+
16
+ # for the examples
17
+
18
+ gem "rails"
19
+ gem "rspec"
20
+ gem "rspec-rails"
21
+ gem "shoulda-matchers"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ai_refactor (0.4.0)
4
+ ai_refactor (0.5.1)
5
5
  colorize (< 2.0)
6
6
  open3 (< 2.0)
7
7
  ruby-openai (>= 3.4.0, < 5.0)
@@ -10,28 +10,179 @@ PATH
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
+ actioncable (7.0.8)
14
+ actionpack (= 7.0.8)
15
+ activesupport (= 7.0.8)
16
+ nio4r (~> 2.0)
17
+ websocket-driver (>= 0.6.1)
18
+ actionmailbox (7.0.8)
19
+ actionpack (= 7.0.8)
20
+ activejob (= 7.0.8)
21
+ activerecord (= 7.0.8)
22
+ activestorage (= 7.0.8)
23
+ activesupport (= 7.0.8)
24
+ mail (>= 2.7.1)
25
+ net-imap
26
+ net-pop
27
+ net-smtp
28
+ actionmailer (7.0.8)
29
+ actionpack (= 7.0.8)
30
+ actionview (= 7.0.8)
31
+ activejob (= 7.0.8)
32
+ activesupport (= 7.0.8)
33
+ mail (~> 2.5, >= 2.5.4)
34
+ net-imap
35
+ net-pop
36
+ net-smtp
37
+ rails-dom-testing (~> 2.0)
38
+ actionpack (7.0.8)
39
+ actionview (= 7.0.8)
40
+ activesupport (= 7.0.8)
41
+ rack (~> 2.0, >= 2.2.4)
42
+ rack-test (>= 0.6.3)
43
+ rails-dom-testing (~> 2.0)
44
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
45
+ actiontext (7.0.8)
46
+ actionpack (= 7.0.8)
47
+ activerecord (= 7.0.8)
48
+ activestorage (= 7.0.8)
49
+ activesupport (= 7.0.8)
50
+ globalid (>= 0.6.0)
51
+ nokogiri (>= 1.8.5)
52
+ actionview (7.0.8)
53
+ activesupport (= 7.0.8)
54
+ builder (~> 3.1)
55
+ erubi (~> 1.4)
56
+ rails-dom-testing (~> 2.0)
57
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
58
+ activejob (7.0.8)
59
+ activesupport (= 7.0.8)
60
+ globalid (>= 0.3.6)
61
+ activemodel (7.0.8)
62
+ activesupport (= 7.0.8)
63
+ activerecord (7.0.8)
64
+ activemodel (= 7.0.8)
65
+ activesupport (= 7.0.8)
66
+ activestorage (7.0.8)
67
+ actionpack (= 7.0.8)
68
+ activejob (= 7.0.8)
69
+ activerecord (= 7.0.8)
70
+ activesupport (= 7.0.8)
71
+ marcel (~> 1.0)
72
+ mini_mime (>= 1.1.0)
73
+ activesupport (7.0.8)
74
+ concurrent-ruby (~> 1.0, >= 1.0.2)
75
+ i18n (>= 1.6, < 2)
76
+ minitest (>= 5.1)
77
+ tzinfo (~> 2.0)
13
78
  ast (2.4.2)
79
+ builder (3.2.4)
14
80
  colorize (0.8.1)
81
+ concurrent-ruby (1.2.2)
82
+ crass (1.0.6)
83
+ date (3.3.3)
84
+ diff-lcs (1.5.0)
15
85
  dotenv (2.8.1)
86
+ erubi (1.12.0)
16
87
  faraday (2.7.4)
17
88
  faraday-net_http (>= 2.0, < 3.1)
18
89
  ruby2_keywords (>= 0.0.4)
19
90
  faraday-multipart (1.0.4)
20
91
  multipart-post (~> 2)
21
92
  faraday-net_http (3.0.2)
93
+ globalid (1.2.1)
94
+ activesupport (>= 6.1)
95
+ i18n (1.14.1)
96
+ concurrent-ruby (~> 1.0)
22
97
  json (2.6.3)
23
98
  language_server-protocol (3.17.0.3)
24
99
  lint_roller (1.0.0)
100
+ loofah (2.21.3)
101
+ crass (~> 1.0.2)
102
+ nokogiri (>= 1.12.0)
103
+ mail (2.8.1)
104
+ mini_mime (>= 0.1.1)
105
+ net-imap
106
+ net-pop
107
+ net-smtp
108
+ marcel (1.0.2)
109
+ method_source (1.0.0)
110
+ mini_mime (1.1.5)
25
111
  minitest (5.18.0)
26
112
  multipart-post (2.3.0)
113
+ net-imap (0.3.7)
114
+ date
115
+ net-protocol
116
+ net-pop (0.1.2)
117
+ net-protocol
118
+ net-protocol (0.2.1)
119
+ timeout
120
+ net-smtp (0.3.3)
121
+ net-protocol
122
+ nio4r (2.5.9)
123
+ nokogiri (1.15.4-arm64-darwin)
124
+ racc (~> 1.4)
27
125
  open3 (0.1.2)
28
126
  parallel (1.23.0)
29
127
  parser (3.2.2.1)
30
128
  ast (~> 2.4.1)
129
+ racc (1.7.1)
130
+ rack (2.2.8)
131
+ rack-test (2.1.0)
132
+ rack (>= 1.3)
133
+ rails (7.0.8)
134
+ actioncable (= 7.0.8)
135
+ actionmailbox (= 7.0.8)
136
+ actionmailer (= 7.0.8)
137
+ actionpack (= 7.0.8)
138
+ actiontext (= 7.0.8)
139
+ actionview (= 7.0.8)
140
+ activejob (= 7.0.8)
141
+ activemodel (= 7.0.8)
142
+ activerecord (= 7.0.8)
143
+ activestorage (= 7.0.8)
144
+ activesupport (= 7.0.8)
145
+ bundler (>= 1.15.0)
146
+ railties (= 7.0.8)
147
+ rails-dom-testing (2.2.0)
148
+ activesupport (>= 5.0.0)
149
+ minitest
150
+ nokogiri (>= 1.6)
151
+ rails-html-sanitizer (1.6.0)
152
+ loofah (~> 2.21)
153
+ nokogiri (~> 1.14)
154
+ railties (7.0.8)
155
+ actionpack (= 7.0.8)
156
+ activesupport (= 7.0.8)
157
+ method_source
158
+ rake (>= 12.2)
159
+ thor (~> 1.0)
160
+ zeitwerk (~> 2.5)
31
161
  rainbow (3.1.1)
32
162
  rake (13.0.6)
33
163
  regexp_parser (2.8.0)
34
164
  rexml (3.2.5)
165
+ rspec (3.12.0)
166
+ rspec-core (~> 3.12.0)
167
+ rspec-expectations (~> 3.12.0)
168
+ rspec-mocks (~> 3.12.0)
169
+ rspec-core (3.12.2)
170
+ rspec-support (~> 3.12.0)
171
+ rspec-expectations (3.12.3)
172
+ diff-lcs (>= 1.2.0, < 2.0)
173
+ rspec-support (~> 3.12.0)
174
+ rspec-mocks (3.12.6)
175
+ diff-lcs (>= 1.2.0, < 2.0)
176
+ rspec-support (~> 3.12.0)
177
+ rspec-rails (6.0.3)
178
+ actionpack (>= 6.1)
179
+ activesupport (>= 6.1)
180
+ railties (>= 6.1)
181
+ rspec-core (~> 3.12)
182
+ rspec-expectations (~> 3.12)
183
+ rspec-mocks (~> 3.12)
184
+ rspec-support (~> 3.12)
185
+ rspec-support (3.12.1)
35
186
  rubocop (1.50.2)
36
187
  json (~> 2.3)
37
188
  parallel (~> 1.10)
@@ -52,6 +203,8 @@ GEM
52
203
  faraday-multipart (>= 1)
53
204
  ruby-progressbar (1.13.0)
54
205
  ruby2_keywords (0.0.5)
206
+ shoulda-matchers (5.3.0)
207
+ activesupport (>= 5.2.0)
55
208
  standard (1.28.2)
56
209
  language_server-protocol (~> 3.17.0.2)
57
210
  lint_roller (~> 1.0)
@@ -63,7 +216,14 @@ GEM
63
216
  standard-performance (1.0.1)
64
217
  lint_roller (~> 1.0)
65
218
  rubocop-performance (~> 1.16.0)
219
+ thor (1.2.2)
220
+ timeout (0.4.0)
221
+ tzinfo (2.0.6)
222
+ concurrent-ruby (~> 1.0)
66
223
  unicode-display_width (2.4.2)
224
+ websocket-driver (0.7.6)
225
+ websocket-extensions (>= 0.1.0)
226
+ websocket-extensions (0.1.5)
67
227
  zeitwerk (2.6.8)
68
228
 
69
229
  PLATFORMS
@@ -73,7 +233,11 @@ DEPENDENCIES
73
233
  ai_refactor!
74
234
  dotenv
75
235
  minitest (~> 5.0)
236
+ rails
76
237
  rake (~> 13.0)
238
+ rspec
239
+ rspec-rails
240
+ shoulda-matchers
77
241
  standard (~> 1.3)
78
242
 
79
243
  BUNDLED WITH
data/README.md CHANGED
@@ -1,22 +1,75 @@
1
- # AI Refactor for Ruby
1
+ # AIRefactor for Ruby
2
2
 
3
- AI Refactor is an experimental tool to use AI to help apply refactoring to code.
3
+ __The goal for AIRefactor is to use LLMs to apply repetitive refactoring tasks to code.__
4
4
 
5
- __The goal for AI Refactor is to help apply repetitive refactoring tasks, not to replace human mind that decides what refactoring is needed.__
5
+ First the human decides what refactoring is needed and builds up a prompt to describe the task, or uses one of AIRefactors provided prompts.
6
+
7
+ AIRefactor then helps to apply the refactoring to one or more files.
8
+
9
+ In some cases, the tool can then check the generated code by running tests and comparing test outputs.
10
+
11
+ #### Notes
12
+
13
+ AI Refactor is an experimental tool and under active development as I explore the idea myself. It may not work as expected, or
14
+ change in ways that break existing functionality.
15
+
16
+ The focus of the tool is work with the Ruby programming language ecosystem, but it can be used with any language.
6
17
 
7
18
  AI Refactor currently uses [OpenAI's ChatGPT](https://platform.openai.com/).
8
19
 
9
- The tool lets the human user prompt the AI with explicit refactoring tasks, and can be run on one or more files at a time.
10
- The tool then uses a LLM to apply the relevant refactor, and if appropriate, checks results by running tests and comparing output.
20
+ ## Examples
21
+
22
+ See the [examples](examples/) directory for some examples of using the tool.
23
+
24
+ You can run the command files to run the example.
25
+
26
+ For example, the first example can be run with: (you can add options if desired, eg `-v` for verbose output and `-d` for debug output)
27
+
28
+ ```shell
29
+ ./exe/ai_refactor examples/ex1_convert_a_rspec_test_to_minitest.yml
30
+ ```
31
+
32
+ You should see:
33
+
34
+ ```
35
+ $ ./exe/ai_refactor examples/ex1_convert_a_rspec_test_to_minitest.yml
36
+ Loading refactor command file 'examples/ex1_convert_a_rspec_test_to_minitest.yml'...
37
+ AI Refactor 1 files(s)/dir(s) '["examples/ex1_input_spec.rb"]' with rails/minitest/rspec_to_minitest refactor
38
+ ====================
39
+ Processing examples/ex1_input_spec.rb...
40
+
41
+ No differences found! Conversion worked!
42
+ Refactor succeeded on examples/ex1_input_spec.rb
43
+
44
+ All files processed successfully!
45
+ Done processing all files!
46
+ ```
47
+
48
+ And find the file `examples/ex1_input_test.rb` has been created. Note the process above also ran the generated test file and compared the output to the original test file.
49
+
50
+ If you see an error, then try to run it again, or use a different GPT model.
11
51
 
12
- The focus of the tool is work with the Ruby programming language ecosystem, but it can be used with any language.
13
52
 
14
53
  ## Available refactors
15
54
 
16
- Currently available:
55
+ Write your own prompt:
56
+
57
+ - `ruby/write_ruby`: provide your own prompt for the AI and expect to output Ruby code (no input files required)
58
+ - `ruby/refactor_ruby`: provide your own refactoring prompt for the AI and expect to output Ruby code
59
+ - `custom`: provide your own prompt for the AI and run against the input files. There is no expectation of the output.
17
60
 
61
+ Use a pre-built prompt:
62
+
63
+ - `minitest/write_test_for_class`: write a minitest test for a given class
18
64
  - `rails/minitest/rspec_to_minitest`: convert RSpec specs to minitest tests in Rails apps
19
- - `generic`: provide your own prompt for the AI and run against the input files
65
+
66
+ ### User supplied prompts, eg `custom`, `ruby/write_ruby` and `ruby/refactor_ruby`
67
+
68
+ Applies the refactor specified by prompting the AI with the user supplied prompt. You must supply a prompt file with the `-p` option.
69
+
70
+ The output is written to `stdout`, or to a file with the `--output` option.
71
+
72
+ User supplied prompts are best configured using a command file, see below.
20
73
 
21
74
  ### `rails/minitest/rspec_to_minitest`
22
75
 
@@ -44,12 +97,6 @@ Refactor succeeded on spec/models/my_thing_spec.rb
44
97
  Done processing all files!
45
98
  ```
46
99
 
47
- ### `generic` (user supplied prompt)
48
-
49
- Applies the refactor specified by prompting the AI with the user supplied prompt. You must supply a prompt file with the `-p` option.
50
-
51
- The output is written to `stdout`, or to a file with the `--output` option.
52
-
53
100
  ### `minitest/write_test_for_class`
54
101
 
55
102
  Writes a minitest test for a given class. The output will, by default, be put into a directory named `test` in the current directory,
@@ -75,13 +122,14 @@ If bundler is not being used to manage dependencies, install the gem by executin
75
122
  See `ai_refactor --help` for more information.
76
123
 
77
124
  ```
78
- Usage: ai_refactor REFACTOR_TYPE INPUT_FILE_OR_DIR [options]
125
+ Usage: ai_refactor REFACTOR_TYPE_OR_COMMAND_FILE INPUT_FILE_OR_DIR [options]
79
126
 
80
- Where REFACTOR_TYPE is one of: ["generic" ... (run ai_refactor --help for full list of refactor types)]
127
+ Where REFACTOR_TYPE_OR_COMMAND_FILE is either the path to a command YML file, or one of the refactor types: ["custom" ... (run ai_refactor --help for full list of refactor types)]
81
128
 
82
129
  -o, --output [FILE] Write output to given file instead of stdout. If no path provided will overwrite input file (will prompt to overwrite existing files). Some refactor tasks will write out to a new file by default. This option will override the tasks default behaviour.
83
130
  -O, --output-template TEMPLATE Write outputs to files instead of stdout. The template is used to create the output name, where the it can have substitutions, '[FILE]', '[NAME]', '[DIR]', '[REFACTOR]' & '[EXT]'. Eg `[DIR]/[NAME]_[REFACTOR][EXT]` (will prompt to overwrite existing files)
84
131
  -c, --context CONTEXT_FILES Specify one or more files to use as context for the AI. The contents of these files will be prepended to the prompt sent to the AI.
132
+ -x, --extra CONTEXT_TEXT Specify some text to be prepended to the prompt sent to the AI as extra information of note.
85
133
  -r, --review-prompt Show the prompt that will be sent to ChatGPT but do not actually call ChatGPT or make changes to files.
86
134
  -p, --prompt PROMPT_FILE Specify path to a text file that contains the ChatGPT 'system' prompt.
87
135
  -f, --diffs Request AI generate diffs of changes rather than writing out the whole file.
@@ -91,11 +139,81 @@ Where REFACTOR_TYPE is one of: ["generic" ... (run ai_refactor --help for full l
91
139
  --max-tokens MAX_TOKENS Specify the max number of tokens of output ChatGPT can generate. Max will depend on the size of the prompt (default 1500)
92
140
  -t, --timeout SECONDS Specify the max wait time for ChatGPT response.
93
141
  --overwrite ANSWER Always overwrite existing output files, 'y' for yes, 'n' for no, or 'a' for ask. Default to ask.
142
+ -N, --no Never overwrite existing output files, same as --overwrite=n.
94
143
  -v, --verbose Show extra output and progress info
95
144
  -d, --debug Show debugging output to help diagnose issues
96
145
  -h, --help Prints this help
97
146
  ```
98
147
 
148
+ ### Interactive mode
149
+
150
+ A basic interactive mode exists too, where you are prompted for options.
151
+
152
+ Start interactive mode by not specifying anything for `REFACTOR_TYPE_OR_COMMAND_FILE` (ie no refactor type or command file)
153
+
154
+ ### Command files and Custom prompts
155
+
156
+ Apart from invoking the tool with CLI options, the tool can also be invoked with a command file.
157
+
158
+ This makes it easier to build custom refactor prompts for projects, and run that custom refactor multiple times.
159
+
160
+ The command file is a YAML file that contains configuration options to pass to the tool.
161
+
162
+ The format of the YAML file is:
163
+
164
+ ```yaml
165
+ # Required options:
166
+ refactor: refactor type name, eg 'ruby/write_ruby'
167
+ # Optional options:
168
+ input_file_paths:
169
+ - input files or directories
170
+ output_file_path: output file or directory
171
+ output_template_path: output file template (see docs)
172
+ prompt_file_path: path
173
+ prompt: |
174
+ A custom prompt to send to ChatGPT if the command needs it (otherwise read from file)
175
+ context_file_paths:
176
+ - file1.rb
177
+ - file2.rb
178
+ # Other configuration options:
179
+ context_text: |
180
+ Some extra info to prepend to the prompt
181
+ diff: true/false (default false)
182
+ ai_max_attempts: max times to generate more if AI does not complete generating (default 3)
183
+ ai_model: ChatGPT model name (default gpt-4)
184
+ ai_temperature: ChatGPT temperature (default 0.7)
185
+ ai_max_tokens: ChatGPT max tokens (default 1500)
186
+ ai_timeout: ChatGPT timeout (default 60)
187
+ overwrite: y/n/a (default a)
188
+ verbose: true/false (default false)
189
+ debug: true/false (default false)
190
+ ```
191
+
192
+ The command file can be invoked by passing it as the first argument to the tool:
193
+
194
+ ```shell
195
+ ai_refactor my_command_file.yml
196
+ ```
197
+
198
+ Other options can be passed on the command line and will override the options in the command file.
199
+
200
+ For example, if the command file contains:
201
+
202
+ ```shell
203
+ ai_refactor my_command_file.yml my_input.rb -d --output foo.rb
204
+ ```
205
+
206
+ ### Prompt template substitutions
207
+
208
+ Prompt text can contain the following substitutions:
209
+
210
+ * `__{{input_file_path}}__`: the path to the input file
211
+ * `__{{output_file_path}}__`: the path to the output file
212
+ * `__{{prompt_header}}__`: the place the pre-build prompt will be injected, if used
213
+ * `__{{prompt_footer}}__`: prompt text that will be inserted after the prompt, eg the "make diffs" prompt if `--diffs` is used
214
+ * `__{{context}}__`: the contents of the context files, if any
215
+ * `__{{content}}__`: the contents of input file, if any
216
+
99
217
  ## Outputs
100
218
 
101
219
  Some refactor tasks will write out to a new file by default, others to stdout.
@@ -117,6 +235,17 @@ eg for the input `my_dir/my_class.rb`
117
235
  - `[REFACTOR]`: `generic`
118
236
  - `[EXT]`: `.rb`
119
237
 
238
+ ## Configuration
239
+
240
+ ### `.ai_refactor` file
241
+
242
+ The tool can be configured using a `.ai_refactor` file in the current directory or in the user's home directory.
243
+
244
+ This file provides default CLI switches to add to any `ai_refactor` command.
245
+
246
+ ## Command history
247
+
248
+ The tool keeps a history of commands run in the `.ai_refactor_history` file in the current working directory.
120
249
 
121
250
  ## Note on performance and ChatGPT version
122
251
 
@@ -0,0 +1 @@
1
+ ex1_input_test.rb
@@ -0,0 +1,7 @@
1
+ refactor: rails/minitest/rspec_to_minitest
2
+ input_file_paths:
3
+ - examples/ex1_input_spec.rb
4
+ # We need to add context here as otherwise to tell the AI to require our local test_helper.rb file so that we can run the tests after
5
+ context_text: "In the output test use `require_relative` to include 'test_helper'."
6
+ # By default, ai_refactor runs "bundle exec rails test" but this isn't going to work here as we are not actually in a Rails app context in the examples
7
+ minitest_run_command: ruby __FILE__
@@ -0,0 +1,32 @@
1
+ require_relative "rails_helper"
2
+
3
+ RSpec.describe MyModel, type: :model do
4
+ subject(:model) { described_class.new }
5
+
6
+ it { is_expected.to validate_presence_of(:name) }
7
+
8
+ it "should allow integer values for age" do
9
+ model.age = 1
10
+ expect(model.age).to eq 1
11
+ end
12
+
13
+ it "should allow string values for name" do
14
+ model.name = "test"
15
+ expect(model.name).to eq "test"
16
+ end
17
+
18
+ it "should be invalid with invalid name" do
19
+ model.name = nil
20
+ expect(model).to be_invalid
21
+ end
22
+
23
+ it "should convert integer values for name" do
24
+ model.name = 1
25
+ expect(model.name).to eq "1"
26
+ end
27
+
28
+ it "should not allow string values for age" do
29
+ model.age = "test"
30
+ expect(model.age).to eq 0
31
+ end
32
+ end
@@ -0,0 +1,21 @@
1
+ require "rails/all"
2
+ require "shoulda-matchers"
3
+
4
+ Shoulda::Matchers.configure do |config|
5
+ config.integrate do |with|
6
+ with.test_framework :rspec
7
+ with.library :rails
8
+ end
9
+ end
10
+
11
+ class MyModel
12
+ include ActiveModel::Model
13
+ include ActiveModel::Attributes
14
+ include ActiveModel::Validations
15
+ include ActiveModel::Validations::Callbacks
16
+
17
+ validates :name, presence: true
18
+
19
+ attribute :name, :string
20
+ attribute :age, :integer
21
+ end
@@ -0,0 +1,14 @@
1
+ require "rails/all"
2
+ require "active_support/testing/autorun"
3
+
4
+ class MyModel
5
+ include ActiveModel::Model
6
+ include ActiveModel::Attributes
7
+ include ActiveModel::Validations
8
+ include ActiveModel::Validations::Callbacks
9
+
10
+ validates :name, presence: true
11
+
12
+ attribute :name, :string
13
+ attribute :age, :integer
14
+ end