├── .github └── workflows │ ├── test-rails6.yml │ └── test-rails7.yml ├── .gitignore ├── LICENSE ├── README.md ├── app └── assets │ └── javascripts │ └── vanilla_nested.js ├── github-assets └── sample.gif ├── lib ├── vanilla_nested.rb └── vanilla_nested │ └── view_helpers.rb ├── package.json ├── test ├── VanillaNestedTestRails7 │ ├── .gitignore │ ├── .ruby-version │ ├── Gemfile │ ├── README.md │ ├── Rakefile │ ├── app │ │ ├── assets │ │ │ ├── config │ │ │ │ └── manifest.js │ │ │ ├── images │ │ │ │ └── .keep │ │ │ └── stylesheets │ │ │ │ └── application.css │ │ ├── channels │ │ │ └── application_cable │ │ │ │ ├── channel.rb │ │ │ │ └── connection.rb │ │ ├── controllers │ │ │ ├── application_controller.rb │ │ │ ├── concerns │ │ │ │ └── .keep │ │ │ └── users_controller.rb │ │ ├── helpers │ │ │ └── application_helper.rb │ │ ├── javascript │ │ │ ├── application.js │ │ │ └── controllers │ │ │ │ ├── application.js │ │ │ │ ├── hello_controller.js │ │ │ │ └── index.js │ │ ├── jobs │ │ │ └── application_job.rb │ │ ├── mailers │ │ │ └── application_mailer.rb │ │ ├── models │ │ │ ├── application_record.rb │ │ │ ├── concerns │ │ │ │ └── .keep │ │ │ ├── pet.rb │ │ │ └── user.rb │ │ └── views │ │ │ ├── layouts │ │ │ ├── application.html.erb │ │ │ ├── mailer.html.erb │ │ │ ├── mailer.text.erb │ │ │ └── turbo.html.erb │ │ │ └── users │ │ │ ├── _form.html.erb │ │ │ ├── _form_with_attributes_on_link_tag.html.erb │ │ │ ├── _form_with_custom_link_tag.html.erb │ │ │ ├── _form_with_undo.html.erb │ │ │ ├── _pet_fields.html.erb │ │ │ ├── _pet_fields_with_attributes_on_link_tag.html.erb │ │ │ ├── _pet_fields_with_custom_link_tag.html.erb │ │ │ ├── _pet_fields_with_undo.html.erb │ │ │ ├── index.html.erb │ │ │ ├── new.html.erb │ │ │ ├── new_with_attributes_on_link_tag.html.erb │ │ │ ├── new_with_custom_link_tag.html.erb │ │ │ └── new_with_undo.html.erb │ ├── bin │ │ ├── bundle │ │ ├── importmap │ │ ├── rails │ │ ├── rake │ │ └── setup │ ├── config.ru │ ├── config │ │ ├── application.rb │ │ ├── boot.rb │ │ ├── cable.yml │ │ ├── credentials.yml.enc │ │ ├── database.yml │ │ ├── environment.rb │ │ ├── environments │ │ │ ├── development.rb │ │ │ ├── production.rb │ │ │ └── test.rb │ │ ├── importmap.rb │ │ ├── initializers │ │ │ ├── assets.rb │ │ │ ├── content_security_policy.rb │ │ │ ├── filter_parameter_logging.rb │ │ │ ├── inflections.rb │ │ │ └── permissions_policy.rb │ │ ├── locales │ │ │ └── en.yml │ │ ├── puma.rb │ │ ├── routes.rb │ │ └── storage.yml │ ├── db │ │ ├── migrate │ │ │ ├── 20210220015506_create_users.rb │ │ │ └── 20210220015510_create_pets.rb │ │ ├── schema.rb │ │ └── seeds.rb │ ├── lib │ │ ├── assets │ │ │ └── .keep │ │ └── tasks │ │ │ └── .keep │ ├── log │ │ └── .keep │ ├── public │ │ ├── 404.html │ │ ├── 422.html │ │ ├── 500.html │ │ ├── apple-touch-icon-precomposed.png │ │ ├── apple-touch-icon.png │ │ ├── favicon.ico │ │ └── robots.txt │ ├── storage │ │ └── .keep │ ├── test │ │ ├── application_system_test_case.rb │ │ ├── channels │ │ │ └── application_cable │ │ │ │ └── connection_test.rb │ │ ├── controllers │ │ │ └── .keep │ │ ├── fixtures │ │ │ └── files │ │ │ │ └── .keep │ │ ├── helpers │ │ │ └── .keep │ │ ├── integration │ │ │ └── .keep │ │ ├── mailers │ │ │ └── .keep │ │ ├── models │ │ │ └── .keep │ │ ├── system │ │ │ ├── .keep │ │ │ ├── html_tag_test.rb │ │ │ ├── undo_test.rb │ │ │ └── vanilla_nested_test.rb │ │ └── test_helper.rb │ ├── tmp │ │ ├── .keep │ │ ├── pids │ │ │ └── .keep │ │ └── storage │ │ │ └── .keep │ └── vendor │ │ ├── .keep │ │ └── javascript │ │ └── .keep └── VanillaNestedTests │ ├── .browserslistrc │ ├── .gitignore │ ├── .ruby-version │ ├── Gemfile │ ├── README.md │ ├── Rakefile │ ├── app │ ├── assets │ │ ├── config │ │ │ └── manifest.js │ │ ├── images │ │ │ └── .keep │ │ └── stylesheets │ │ │ └── application.css │ ├── channels │ │ └── application_cable │ │ │ ├── channel.rb │ │ │ └── connection.rb │ ├── controllers │ │ ├── application_controller.rb │ │ ├── concerns │ │ │ └── .keep │ │ └── users_controller.rb │ ├── helpers │ │ └── application_helper.rb │ ├── javascript │ │ ├── channels │ │ │ ├── consumer.js │ │ │ └── index.js │ │ ├── controllers │ │ │ ├── application.js │ │ │ ├── hello_controller.js │ │ │ └── index.js │ │ └── packs │ │ │ ├── application.js │ │ │ └── application_turbo.js │ ├── jobs │ │ └── application_job.rb │ ├── mailers │ │ └── application_mailer.rb │ ├── models │ │ ├── application_record.rb │ │ ├── concerns │ │ │ └── .keep │ │ ├── pet.rb │ │ └── user.rb │ └── views │ │ ├── layouts │ │ ├── application.html.erb │ │ ├── mailer.html.erb │ │ ├── mailer.text.erb │ │ └── turbo.html.erb │ │ └── users │ │ ├── _form.html.erb │ │ ├── _form_with_attributes_on_link_tag.html.erb │ │ ├── _form_with_custom_link_tag.html.erb │ │ ├── _form_with_undo.html.erb │ │ ├── _pet_fields.html.erb │ │ ├── _pet_fields_with_attributes_on_link_tag.html.erb │ │ ├── _pet_fields_with_custom_link_tag.html.erb │ │ ├── _pet_fields_with_undo.html.erb │ │ ├── index.html.erb │ │ ├── new.html.erb │ │ ├── new_with_attributes_on_link_tag.html.erb │ │ ├── new_with_custom_link_tag.html.erb │ │ └── new_with_undo.html.erb │ ├── babel.config.js │ ├── bin │ ├── bundle │ ├── rails │ ├── rake │ ├── setup │ ├── spring │ ├── update-gem │ ├── webpack │ ├── webpack-dev-server │ └── yarn │ ├── config.ru │ ├── config │ ├── application.rb │ ├── boot.rb │ ├── cable.yml │ ├── credentials.yml.enc │ ├── database.yml │ ├── environment.rb │ ├── environments │ │ ├── development.rb │ │ ├── production.rb │ │ └── test.rb │ ├── initializers │ │ ├── application_controller_renderer.rb │ │ ├── assets.rb │ │ ├── backtrace_silencers.rb │ │ ├── content_security_policy.rb │ │ ├── cookies_serializer.rb │ │ ├── filter_parameter_logging.rb │ │ ├── inflections.rb │ │ ├── mime_types.rb │ │ └── wrap_parameters.rb │ ├── locales │ │ └── en.yml │ ├── puma.rb │ ├── routes.rb │ ├── spring.rb │ ├── storage.yml │ ├── webpack │ │ ├── development.js │ │ ├── environment.js │ │ ├── production.js │ │ └── test.js │ └── webpacker.yml │ ├── db │ ├── migrate │ │ ├── 20210220015506_create_users.rb │ │ └── 20210220015510_create_pets.rb │ ├── schema.rb │ └── seeds.rb │ ├── lib │ ├── assets │ │ └── .keep │ └── tasks │ │ └── .keep │ ├── log │ └── .keep │ ├── package.json │ ├── postcss.config.js │ ├── public │ ├── 404.html │ ├── 422.html │ ├── 500.html │ ├── apple-touch-icon-precomposed.png │ ├── apple-touch-icon.png │ ├── favicon.ico │ └── robots.txt │ ├── storage │ └── .keep │ ├── test │ ├── application_system_test_case.rb │ ├── channels │ │ └── application_cable │ │ │ └── connection_test.rb │ ├── controllers │ │ └── .keep │ ├── fixtures │ │ ├── .keep │ │ └── files │ │ │ └── .keep │ ├── helpers │ │ ├── .keep │ │ └── vanilla_nested_helpers_test.rb │ ├── integration │ │ └── .keep │ ├── mailers │ │ └── .keep │ ├── models │ │ └── .keep │ ├── system │ │ ├── .keep │ │ ├── html_tag_test.rb │ │ ├── undo_test.rb │ │ └── vanilla_nested_test.rb │ └── test_helper.rb │ ├── tmp │ └── .keep │ ├── vendor │ └── .keep │ └── yarn.lock └── vanilla_nested.gemspec /.github/workflows/test-rails6.yml: -------------------------------------------------------------------------------- 1 | name: Tests Rails 6 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | 10 | defaults: 11 | run: 12 | working-directory: ./test/VanillaNestedTests 13 | 14 | jobs: 15 | test: 16 | runs-on: ubuntu-latest 17 | 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | ruby: 22 | - 2.6 23 | - 2.7 24 | 25 | steps: 26 | - uses: actions/checkout@v3 27 | - name: Setup Ruby 28 | uses: ruby/setup-ruby@v1 29 | with: 30 | ruby-version: ${{ matrix.ruby }} 31 | working-directory: test/VanillaNestedTests 32 | bundler-cache: true 33 | - uses: actions/setup-node@v2 34 | with: 35 | node-version: "14" 36 | - name: YARN 37 | uses: bahmutov/npm-install@v1 38 | with: 39 | working-directory: test/VanillaNestedTests 40 | - name: Unit tests 41 | run: bundle exec rails test 42 | - name: System tests 43 | run: bundle exec rails test:system 44 | -------------------------------------------------------------------------------- /.github/workflows/test-rails7.yml: -------------------------------------------------------------------------------- 1 | name: Tests Rails 7 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | 10 | defaults: 11 | run: 12 | working-directory: ./test/VanillaNestedTestRails7 13 | 14 | jobs: 15 | test: 16 | runs-on: ubuntu-latest 17 | 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | ruby: 22 | - 2.7 23 | - "3.0" 24 | - 3.1 25 | - 3.2 26 | 27 | steps: 28 | - uses: actions/checkout@v3 29 | - name: Setup Ruby 30 | uses: ruby/setup-ruby@v1 31 | with: 32 | ruby-version: ${{ matrix.ruby }} 33 | working-directory: test/VanillaNestedTestRails7 34 | bundler-cache: true 35 | - name: Unit tests 36 | run: bundle exec rails test 37 | - name: System tests 38 | run: bundle exec rails test:system 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | test/VanillaNestedTests/node_modules 2 | test/VanillaNestedTests/Gemfile.lock 3 | test/VanillaNestedTestRails7/Gemfile.lock 4 | notes.txt -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Ariel Juodziukynas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vanilla-nested 2 | 3 | Rails dynamic nested forms using vanilla JS 4 | 5 | Similar to cocoon, but with no jquery dependency! 6 | 7 | Example: 8 | 9 | ![sample-gif](./github-assets/sample.gif) 10 | 11 | # Installation 12 | 13 | Just add it to your gemfile 14 | 15 | ```ruby 16 | gem 'vanilla_nested' 17 | 18 | # or, to use latest code from git: 19 | gem 'vanilla_nested', github: 'arielj/vanilla-nested', branch: :main 20 | ``` 21 | 22 | ## Using Sprockets 23 | 24 | Require the js: 25 | 26 | ``` 27 | //= require vanilla_nested 28 | ``` 29 | 30 | ## Using Webpacker 31 | 32 | Add the package too (gem is required for the helper methods) using: 33 | 34 | ```sh 35 | yarn add vanilla-nested 36 | 37 | # or, to use latest code from git: 38 | yarn add arielj/vanilla-nested 39 | ``` 40 | 41 | And then use it in your application.js as: 42 | 43 | ```js 44 | import "vanilla-nested"; 45 | ``` 46 | 47 | ## Using Importmaps in Rails 7 48 | 49 | Add the importmap config: 50 | 51 | ```rb 52 | pin "vanilla-nested", to: "vanilla_nested.js", preload: true 53 | ``` 54 | 55 | And then use it in your application.js as: 56 | 57 | ```js 58 | import "vanilla-nested"; 59 | ``` 60 | 61 | # Updating 62 | 63 | To update the gem use either: 64 | 65 | ``` 66 | gem update vanilla_nested # if using the gem from RubyGems 67 | 68 | # or 69 | 70 | gem update --source vanilla_nested # if using the gem from github 71 | ``` 72 | 73 | If using webpacker, you need to update the node package too with: 74 | 75 | ``` 76 | yarn upgrade vanilla-nested 77 | ``` 78 | 79 | > You can clear the webpacker cache just in case if changes are not reflecting with `rails webpacker:clobber` 80 | 81 | # Usage 82 | 83 | ## Backend prerequisites 84 | 85 | ```ruby 86 | # models/order.rb 87 | class Order < ApplicationRecord 88 | has_many :order_items 89 | accepts_nested_attributes_for :order_items, reject_if: :all_blank, allow_destroy: true 90 | ``` 91 | 92 | ```ruby 93 | # models/order_item.rb 94 | class OrderItem < ApplicationRecord 95 | belongs_to :order 96 | end 97 | ``` 98 | 99 | ```ruby 100 | class OrdersController < ApplicationController 101 | ... 102 | def order_params 103 | params.require(:order).permit(:attr, order_items_attributes: [:id, :attr1, :attr2, :_destroy]) 104 | end 105 | end 106 | ``` 107 | 108 | ### Adding/Removing nested fields 109 | 110 | ```HTML+ERB 111 | # orders/_order_item_fields.html.erb 112 |
113 | <%= form.text_field :attr1 %> 114 | <%= form.select :attr2 ..... %> 115 | <%= link_to_remove_nested(form) %> 116 |
117 | ``` 118 | 119 | ```HTML+ERB 120 | # order/form.html.erb 121 | <%= form_for product do |form| %> 122 | <%= form.text_field :attr %> 123 | 124 | <%= link_to_add_nested(form, :order_items, '#order-items') %> 125 |
126 | <%= form.fields_for :order_items do |order_item_f| %> 127 | <%= render 'order_item_fields', form: order_item_f %> 128 | <% end %> 129 |
130 | <% end %> 131 | ``` 132 | 133 | Note that: 134 | 135 | - `link_to_remove_nested` receives the nested form as a parameter, it adds a hidden `[_destroy]` field 136 | - `link_to_add_nested` expects the form builder, the name of the association and the selector of the container where the gem will insert the new fields 137 | 138 | # Customizing link_to_add_nested 139 | 140 | #### Link text 141 | 142 | The default value is `Add `, but it can be changed using the parameter `link_text`: 143 | 144 | ```Ruby 145 | link_to_add_nested(form, :order_items, '#order-items', link_text: I18n.t(:some_key)) 146 | ``` 147 | 148 | This way you can, for example, internationalize the text. 149 | 150 | #### Link classes 151 | 152 | By default, the link to add new fields has the class `vanilla-nested-add` which is required, but you can add more classes passing a string: 153 | 154 | ```Ruby 155 | link_to_add_nested(form, :order_items, '#order-items', link_classes: 'btn btn-primary') 156 | ``` 157 | 158 | This way you can style the link with no need of targeting the specific vanilla nested class. 159 | 160 | #### Insert position 161 | 162 | By default, new fields are appended to the container, you can change that with the `insert_method` option. For now, only `:append` and `:prepend` are supported: 163 | 164 | ```Ruby 165 | link_to_add_nested(form, :order_items, '#order-items', insert_method: :prepend) 166 | ``` 167 | 168 | #### Partial name 169 | 170 | The default partial's name is inferred using the association's class name. If your Order has_many :order_items and the class of those items is OrderItem, then the inferred name is `order_item_fields`. You can use any partial name you like, though: 171 | 172 | ```Ruby 173 | link_to_add_nested(form, :order_items, '#order-items', partial: 'my_partial') 174 | ``` 175 | 176 | #### Form variable used in the partial 177 | 178 | `link_to_add_nested` needs to render an empty template in order to later append/prepend it. To do that, it passes the form as a local variable. If your partial uses `form`, you don't have to do anything, but if you using another variable name, just customize it here. 179 | 180 | ```HTML+ERB 181 | # orders/_order_item_fields.html.erb 182 |
183 | <%= ff.text_field :attr1 %> 184 | <%= ff.select :attr2 ..... %> 185 | <%= link_to_remove_nested(ff) # adds a link to remove the element %> 186 |
187 | ``` 188 | 189 | ```Ruby 190 | link_to_add_nested(form, :order_items, '#order-items', partial_form_variable: :ff) 191 | ``` 192 | 193 | You can also pass more local variables to the partial by setting the partial_locals value. 194 | 195 | ```Ruby 196 | link_to_add_nested(form, :order_items, '#order-items', partial_locals: { key: 'value' }) 197 | ``` 198 | 199 | #### Tag 200 | 201 | The HTML tag that will be generated. An `` tag by default. 202 | 203 | ```Ruby 204 | link_to_add_nested(form, :order_items, '#order-items', tag: 'span') 205 | ``` 206 | 207 | #### Tag Attributes 208 | 209 | HTML attributes to set for the generated HTML tag. It's a has with key value pairs user for the `content_tag` call, so it support any attribute/value pair supported by [`content_tag`](https://apidock.com/rails/ActionView/Helpers/TagHelper/content_tag) 210 | 211 | ```Ruby 212 | link_to_add_nested(form, :order_items, '#order-items', link_text: '+', tag_attributes: {title: "Add Order"}) 213 | # + 214 | ``` 215 | 216 | `class` attributes are appended to the `vanilla-nested-add` class and the custom classes specified with the `link_classes` argument. 217 | 218 | ```Ruby 219 | link_to_add_nested(form, :order_items, '#order-items', link_text: '+', tag_attributes: {class: "some-class"}, link_classes: 'another-class') 220 | # + 221 | ``` 222 | 223 | #### Link content 224 | 225 | If you need html content, you can use a block: 226 | 227 | ```erb 228 | <%= link_to_add_nested(form, :order_items, '#order-items') do %> 229 | 230 | <% end %> 231 | ``` 232 | 233 | # Customizing link_to_remove_nested 234 | 235 | #### Link text 236 | 237 | The default value is `"X"`, but it can be changed using the parameter `link_text`: 238 | 239 | ```Ruby 240 | link_to_remove_nested(form, link_text: "remove") 241 | ``` 242 | 243 | #### Link content 244 | 245 | If you need html content, you can use a block: 246 | 247 | ```erb 248 | <%= link_to_remove_nested(form) do %> 249 | 250 | <% end %> 251 | ``` 252 | 253 | #### Link classes 254 | 255 | By default, the link to remove fields has the class `vanilla-nested-remove` which is required, but you can add more classes passing a space separated string: 256 | 257 | ```Ruby 258 | link_to_remove_nested(form, link_classes: 'btn btn-primary') 259 | ``` 260 | 261 | This way you can style the link with no need of targeting the specific vanilla nested class. 262 | 263 | #### Fields wrapper 264 | 265 | By default, the link to remove the fields assumes it's a direct child of the wrapper of the fields. You can customize this if you can't make it a direct child. 266 | 267 | ```HTML+ERB 268 | # orders/_order_item_fields.html.erb 269 |
270 |
271 | <%= ff.text_field :attr1 %> 272 | <%= ff.select :attr2 ..... %> 273 |
274 | <%= link_to_remove_nested(ff, fields_wrapper_selector: '.wrapper-div') # if we don't set this, it will only hide the span %> 275 |
276 | ``` 277 | 278 | Note that: 279 | 280 | - The link MUST be a descendant of the fields wrapper, it may not be a direct child, but the look up of the wrapper uses JavaScript's `closest()` method, so it looks on the ancestors. 281 | - Since this uses JavaScript's `closest()`, there is no IE supported (https://caniuse.com/#search=closest). You may want to add a polyfill or define the method manually if you need to support it. 282 | 283 | #### Tag 284 | 285 | The HTML tag that will be generated. An `` tag by default. 286 | 287 | ```Ruby 288 | link_to_remove_nested(ff, tag: 'p') 289 | ``` 290 | 291 | #### Tag Attributes 292 | 293 | HTML attributes to set for the generated HTML tag. It's a has with key value pairs user for the `content_tag` call, so it support any attribute/value pair supported by [`content_tag`](https://apidock.com/rails/ActionView/Helpers/TagHelper/content_tag) 294 | 295 | ```Ruby 296 | link_to_remove_nested(ff, link_text: 'X', tag_attributes: {title: "Delete!"}) 297 | # X 298 | ``` 299 | 300 | `class` attributes are appended to the `vanilla-nested-remove` class and the custom classes specified with the `link_classes` argument, just like the `link_to_add_nested` helper. 301 | 302 | #### Undoing 303 | 304 | You can tell the plugin to add an "undo" link right after removing the fields (as a direct child of the fields wrapper! this is not customizable!). 305 | 306 | ```Ruby 307 | link_to_remove_nested(ff, undo_link_timeout: 2000, undo_link_text: I18n.t('undo_remove_fields'), undo_link_classes: 'btn btn-secondary') 308 | ``` 309 | 310 | Options are: 311 | 312 | - `undo_link_timeout`: milliseconds, greater than 0 to turn the feature on, default: `nil` 313 | - `undo_link_text`: string with the text of the link, great for internationalization, default: `'Undo'` 314 | - `undo_link_classes`: space separated string, default: `''` 315 | 316 | # Events 317 | 318 | There are some events that you can listen to add custom callbacks on different moments. All events bubbles up the dom, so you can listen for them on any ancestor. 319 | 320 | #### 'vanilla-nested:fields-added' 321 | 322 | Triggered right after the fields wrapper was inserted on the container. 323 | 324 | ```Javascript 325 | document.addEventListener('vanilla-nested:fields-added', function(e){ 326 | // e.type == 'vanilla-nested:fields-added' 327 | // e.target == container div of the fields 328 | // e.detail.triggeredBy == the "add" link 329 | // e.detail.added == the fields wrapper just inserted 330 | }) 331 | ``` 332 | 333 | #### 'vanilla-nested:fields-limit-reached' 334 | 335 | Triggered right after the fields wrapper was inserted on the container if the current count is >= limit, where limit is the value configured on the model: `accepts_nested_attributes_for :assoc, limit: 5`. You can listen to this event to disable the "add" link for example, or to show a warning. 336 | 337 | ```Javascript 338 | document.addEventListener('vanilla-nested:fields-limit-reached', function(e){ 339 | // e.type == 'vanilla-nested:fields-added' 340 | // e.target == container div of the fields 341 | // e.detail.triggeredBy == the "add" link 342 | }) 343 | ``` 344 | 345 | #### 'vanilla-nested:fields-removed' 346 | 347 | Triggered when the fields wrapper if fully hidden (aka ""removed""), that is: after clicking the "remove" link with no timeout OR after the timeout finished. 348 | 349 | ```Javascript 350 | document.addEventListener('vanilla-nested:fields-removed', function(e){ 351 | // e.type == 'vanilla-nested:fields-removed' 352 | // e.target == fields wrapper ""removed"" 353 | // e.detail.triggeredBy == the "remove" link if no undo action, the 'undo' link if it was triggered by the timeout }) 354 | ``` 355 | 356 | #### 'vanilla-nested:fields-hidden' 357 | 358 | Triggered when the fields wrapper if hidden with an undo option. 359 | 360 | ```Javascript 361 | document.addEventListener('vanilla-nested:fields-hidden', function(e){ 362 | // e.type == 'vanilla-nested:fields-hidden' 363 | // e.target == fields wrapper hidden 364 | // e.detail.triggeredBy == the "remove" link 365 | }) 366 | ``` 367 | 368 | > **Remove vs Hidden** 369 | > 370 | > Behind the scene, the wrapper is never actually removed, because we need to send the `[_destroy]` parameter. But there are 2 different stages when removing it. 371 | > 372 | > - If there's no "undo" action configured, the wrapped is set to `display: none` and considered "removed". 373 | > - If you use the "undo" feature, first the children of the wrapper are hidden (triggering the `hidden` event) and then, after the timeout passes, the wrapper is set to `display: none` (triggering the `removed` event). 374 | 375 | #### 'vanilla-nested:fields-hidden-undo' 376 | 377 | Triggered when the user undo the removal using the "undo" link. 378 | 379 | ```Javascript 380 | document.addEventListener('vanilla-nested:fields-hidden-undo', function(e){ 381 | // e.type == 'vanilla-nested:fields-hidden-undo' 382 | // e.target == fields wrapper unhidden 383 | // e.detail.triggeredBy == the "undo" link 384 | }) 385 | ``` 386 | 387 | ## Testing 388 | 389 | You can run the tests following these commands: 390 | 391 | - cd test/VanillaNestedTests # move to the rails app dir 392 | - bin/setup # install bundler, gems and yarn packages 393 | - rails test # unit tests 394 | - rails test:system # system tests 395 | 396 | > If you make changes in the JS files, you have to tell yarn to refresh the code inside the node_modules folder running `./bin/update-gem` (or `yarn upgrade vanilla-nested` and `rails webpacker:clobber`), and then restart the rails server or re-run the tests. 397 | 398 | # Version 1.1.0 Changes 399 | 400 | #### Change the method to infere the name of the partial 401 | 402 | Before, it used `SomeClass.name.downcase`, this created a problem for classes with more than one word: 403 | 404 | - User => 'user_fields' 405 | - SomeClass => 'someclass_fields' 406 | 407 | Now it uses `SomeClass.name.underscore`: 408 | 409 | - User => 'user_fields' 410 | - SomeClass => 'some_class_fields' 411 | 412 | If you used the old version, you'll need to change the partial name or provide the old name as the `partial:` argument. 413 | 414 | #### Fix some RuboCop style suggestions 415 | 416 | Mostly single/double quotes, spacing, etc. 417 | 418 | #### Added some Solagraph related doc for the view helpers 419 | 420 | Just so Solargraph plugins on editors like VS-Code can give you some documentation. 421 | 422 | #### Added some documentation on the code 423 | 424 | Mostly on the javascript code 425 | 426 | #### Added node module config 427 | 428 | So it can be used as a node module using yarn to integrate it using webpacker. 429 | 430 | # Version 1.2.0 Changes 431 | 432 | #### New event for the "limit" option of `accepts_nested_attributes_for` 433 | 434 | You can listen to the `vanilla-nested:fields-limit-reached` event that will fire when container has more or equals the amount of children than the `limit` option set on the `accepts_nested_attributes_for` configuration. 435 | 436 | # Version 1.2.1 Changes 437 | 438 | #### Removed "onclick" attribute for helpers and add event listeners within js 439 | 440 | If you were using webpacker, remember to replace the vanilla_nested.js file in your app/javascript folder 441 | 442 | # Version 1.2.2 Changes 443 | 444 | #### Added "link_classes" option to "link_to_remove_nested" 445 | 446 | You can set multiple classes for the "X" link 447 | 448 | #### Added a "link_content" block parameter for both link helpers 449 | 450 | You can pass a block to use as the content for the add and remove links 451 | 452 | # Version 1.2.3 Changes 453 | 454 | #### Fix using nested html elements as the content for buttons 455 | 456 | There was an error when using the helpers with things like: 457 | 458 | ```erb 459 | <%= link_to_add_nested(form, :pets, '#pets') do %> 460 | Add Pet 461 | <% end %> 462 | ``` 463 | 464 | It would detect the wrong element for the click event, making the JS fail. 465 | 466 | # Version 1.2.4 Changes 467 | 468 | Play nicely with Turbolinks' `turbolinks:load` event. 469 | 470 | # Version 1.2.5 Changes 471 | 472 | License change from GPL to MIT 473 | 474 | # Version 1.3.0 Changes 475 | 476 | #### Custom generated HTML element tag 477 | 478 | The default HTML tag generated by `link_to_add/remove_nested` is an `A` tag, but it can now be customized with the `tag:` keyword argument: 479 | 480 | ```erb 481 | <%= link_to_add_nested(form, :pets, '#pets', tag: 'span') %> 482 | ``` 483 | 484 | #### Extra class added to dynamically added fields 485 | 486 | Elements added dynamically now have an extra `added-by-vanilla-nested` class, used internally and helpful for styling. 487 | 488 | #### Removed elements are actually removed from the document 489 | 490 | Before, the elements were just hidden using `display: none` on the wrapper. That lead to issues when the input elements had validations that were triggered by the browser but the elements where not accessible anymore. With this new version, removing a nested set of fields removes all the content. 491 | 492 | #### Correct calculation for the limit-reached event 493 | 494 | If the `accepts_nested_attributes_for` configuration has a limit, this gem was counting the number of children wrong (it was counting removed elements and extra children of the wrapper). This fixes that by only counting the `[_destroy]` hidden fields with value `0`. 495 | 496 | # Version 1.4.0 Changes 497 | 498 | #### Custom HTML attributes for the generated HTML element tag 499 | 500 | Both `link_to_add_nested` and `link_to_remove_nested` now support a `tag_attributes` keyword argument with key value pairs representing attributes and values for the generated HTML tag. 501 | 502 | You can use this to customize the tag as you need: 503 | 504 | - you can add a `title` for your `a` tag to make them more accessible: 505 | 506 | ```Ruby 507 | link_to_remove_nested(ff, link_text: 'X', tag_attributes: {title: "Delete!"}) 508 | # X 509 | ``` 510 | 511 | - you can set a `type`, `name` and `value` for a `button` tag if you want to have a non-javascript submit action to fallback in case the user has Javascript disabled: 512 | 513 | ```Ruby 514 | link_to_add_nested(form, :order_items, '#order-items', tag: 'button', tag_attributes: {type: 'submit', name: 'commit', value: 'add-nested' }) 515 | # now you have a button tag that will submit your form with a `commit` param with `add-nested` as the value to handle a non-javascript fallback to add nested fields an re-render the form! 516 | ``` 517 | 518 | - you can set any valid html attribute accepted by [`content_tag`](https://apidock.com/rails/ActionView/Helpers/TagHelper/content_tag) 519 | 520 | # Version 1.5.0 Changes 521 | 522 | #### Added Integration with the `turbo` Gem 523 | 524 | The JavaScript part of the gem now plays nicely with the `turbo` gem by initializing the needed events when the `turbo:load` event is fired. 525 | 526 | # Version 1.5.1 Changes 527 | 528 | #### Yarn/NPM Packages 529 | 530 | Node package can be installed using npm or yarn without using the GitHub repo. This improves the size of the bundle and allows version flags. 531 | 532 | # Version 1.6.0 Changes 533 | 534 | #### Fix undeclared variables 535 | 536 | https://github.com/arielj/vanilla-nested/pull/45 thanks @gmeir. 537 | 538 | #### Added engine config to support importmaps 539 | 540 | You can pin the vanilla-nested module. A Rails 7 sample app is added to the test directory. 541 | 542 | # Version 1.6.1 Changes 543 | 544 | #### Fix elements' style after undo 545 | 546 | When undoing a removal, the gem was setting `display: initial` to all the elements. Now it sets the `display` value it had before hidding the element. 547 | 548 | > Remember to update both gem and package https://github.com/arielj/vanilla-nested#update 549 | 550 | # Version 1.6.2 Changes 551 | 552 | #### Event listeners are now added once to the `document` 553 | 554 | Attach the vanilla-nested event listeners to the document object. This fixes [issues](https://github.com/arielj/vanilla-nested/issues/47) with turbo/hotwire where the listener was not being attached to the new elements added to the DOM. Thanks to @lenilsonjr for testing these changes! 555 | 556 | # Version 1.7.0 Changes 557 | 558 | #### Fix initialization of Vanilla Nested when using importmaps and Safari 559 | 560 | The shim to support importmaps in Safari was not firing the load events as the code was expecting. This patches that by considering if the DOM is already ready when the code loads. 561 | 562 | # Version 1.7.1 Changes 563 | 564 | #### New classes added 565 | 566 | When removing a nested element, a `hidden-by-vanilla-nested` class is added if there's a timeout. The class is removed if the action is undone. 567 | 568 | When removing a nested element, a `removed-by-vanilla-nested` class is added if there's no timeout or after the timeout expires. 569 | 570 | Thanks to @kikyous for the contribution! 571 | 572 | #### Tests in multiple Ruby versions 573 | 574 | Automated tests now run in multiple Ruby versions in CI. 575 | 576 | This change has no impact in the use of the gem, but I wanted to thank @petergoldstein for their contribution! 577 | 578 | #### New `partial_locals` option for `link_to_add_nested` 579 | 580 | Now you can pass a new option with `locals` for the fields wrapper partial. Check https://github.com/arielj/vanilla-nested/pull/64 for an example. Thanks to @gregogalante for the contribution! 581 | -------------------------------------------------------------------------------- /app/assets/javascripts/vanilla_nested.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | // Get the html from the data attribute and insert the new fields on the container 3 | // "event" is the click event of the link created by the rails helper 4 | window.addVanillaNestedFields = function(element) { 5 | if (!element.classList.contains('vanilla-nested-add')) 6 | element = element.closest('.vanilla-nested-add') 7 | 8 | const data = element.dataset; 9 | const container = document.querySelector(data.containerSelector); 10 | const newHtml = data.html.replace(/_idx_placeholder_/g, Date.now()); 11 | 12 | // insert and store reference 13 | let inserted; 14 | switch (data.methodForInsert) { 15 | case ('append'): 16 | container.insertAdjacentHTML('beforeend', newHtml); 17 | inserted = container.lastElementChild; 18 | break; 19 | case ('prepend'): 20 | container.insertAdjacentHTML('afterbegin', newHtml); 21 | inserted = container.firstElementChild; 22 | break; 23 | } 24 | 25 | // add a class to show it was added dynamically 26 | inserted.classList.add('added-by-vanilla-nested'); 27 | 28 | _dispatchEvent(container, 'vanilla-nested:fields-added', element, {added: inserted}) 29 | 30 | // dispatch an event if we reached the limit configured on the model 31 | if (data.limit) { 32 | let nestedElements = container.querySelectorAll('[name$="[_destroy]"][value="0"]').length; 33 | if (nestedElements >= data.limit) 34 | _dispatchEvent(container, 'vanilla-nested:fields-limit-reached', element) 35 | } 36 | } 37 | 38 | // Removes the fields or hides them until the undo timer times out 39 | // "event" is the click event of the link created by the rails helper 40 | window.removeVanillaNestedFields = function(element) { 41 | if (!element.classList.contains('vanilla-nested-remove')) 42 | element = element.closest('.vanilla-nested-remove') 43 | 44 | const data = element.dataset; 45 | let wrapper = element.parentElement; 46 | const sel = data.fieldsWrapperSelector; 47 | if (sel) wrapper = element.closest(sel); 48 | 49 | if (data.undoTimeout) { 50 | hideFieldsWithUndo(wrapper, element); 51 | _dispatchEvent(wrapper, 'vanilla-nested:fields-hidden', element); 52 | } else { 53 | hideWrapper(wrapper); 54 | unhideFields(wrapper); 55 | _dispatchEvent(wrapper, 'vanilla-nested:fields-removed', element); 56 | } 57 | wrapper.querySelector('[name$="[_destroy]"]').value = '1'; 58 | } 59 | 60 | // Hides an element, mainly the wrapper of a group of fields 61 | // "wrapper" is the wrapper of the link to remove fields 62 | function hideWrapper(wrapper) { 63 | if (wrapper.classList.contains('added-by-vanilla-nested')) { 64 | wrapper.remove(); 65 | } else { 66 | wrapper.classList.add('removed-by-vanilla-nested'); 67 | const destroyInput = wrapper.querySelector('[name$="[_destroy]"'); 68 | wrapper.innerHTML = ''; 69 | wrapper.insertAdjacentElement('afterbegin', destroyInput); 70 | } 71 | } 72 | 73 | // Unhides the children given a fields wrapper 74 | // "wrapper" is the wrapper of the link to remove fields 75 | function unhideFields(wrapper) { 76 | [...wrapper.children].forEach(child => { 77 | if (child.dataset.hasAttributeStyle) { 78 | child.style.display = child.dataset.originalDisplay; 79 | } else { 80 | child.removeAttribute("style"); 81 | } 82 | }); 83 | } 84 | 85 | // Hides an element and adds an "undo" link to unhide it 86 | // "wrapper" is the wrapper to hide 87 | // "element" is the link to remove the wrapper 88 | function hideFieldsWithUndo(wrapper, element) { 89 | wrapper.classList.add('hidden-by-vanilla-nested'); 90 | [...wrapper.children].forEach(child => { 91 | // store original style for after undo 92 | if (child.getAttribute("style")) { 93 | child.dataset.hasAttributeStyle = true; 94 | child.dataset.originalDisplay = child.style.display; 95 | } 96 | 97 | child.style.display = 'none'; 98 | }); 99 | 100 | // add the 'undo' link with it's callback 101 | const undoLink = _createUndoWithElementsData(element.dataset); 102 | wrapper.appendChild(undoLink); 103 | 104 | const _onUndoClicked = function(e) { 105 | e.preventDefault(); 106 | clearTimeout(timer); 107 | unhideFields(wrapper); 108 | wrapper.querySelector('[name$="[_destroy]"]').value = '0'; 109 | wrapper.classList.remove('hidden-by-vanilla-nested'); 110 | _dispatchEvent(wrapper, 'vanilla-nested:fields-hidden-undo', undoLink); 111 | undoLink.remove(); 112 | } 113 | 114 | undoLink.addEventListener('click', _onUndoClicked); 115 | 116 | // start the timer 117 | const _onTimerCompleted = function() { 118 | hideWrapper(wrapper); 119 | wrapper.classList.remove('hidden-by-vanilla-nested'); 120 | unhideFields(wrapper); 121 | _dispatchEvent(wrapper, 'vanilla-nested:fields-removed', undoLink); 122 | undoLink.remove(); 123 | } 124 | 125 | let ms = element.dataset.undoTimeout; 126 | let timer = setTimeout(_onTimerCompleted, ms); 127 | } 128 | 129 | function _dispatchEvent(element, eventName, triggeredBy, details) { 130 | if (!details) details = {}; 131 | details.triggeredBy = triggeredBy; 132 | 133 | let event = new CustomEvent(eventName, {bubbles: true, detail: details}) 134 | element.dispatchEvent(event); 135 | } 136 | 137 | function _createUndoWithElementsData(data) { 138 | const undo = document.createElement('A'); 139 | 140 | undo.classList.add('vanilla-nested-undo'); 141 | const classes = data.undoLinkClasses; 142 | if (classes) 143 | undo.classList.add(...classes.split(' ')); 144 | 145 | undo.innerText = data.undoText; 146 | 147 | return undo; 148 | } 149 | 150 | function initVanillaNested() { 151 | document.addEventListener('click', ev => { 152 | const addVanillaNested = 153 | ev.target.classList.contains('vanilla-nested-add') || 154 | ev.target.closest('.vanilla-nested-add'); 155 | 156 | if (addVanillaNested) { 157 | ev.preventDefault(); 158 | addVanillaNestedFields(ev.target); 159 | } 160 | }) 161 | 162 | document.addEventListener('click', ev => { 163 | const removeVanillaNested = 164 | ev.target.classList.contains('vanilla-nested-remove') || 165 | ev.target.closest('.vanilla-nested-remove'); 166 | 167 | if (removeVanillaNested) { 168 | ev.preventDefault(); 169 | removeVanillaNestedFields(ev.target); 170 | } 171 | }) 172 | } 173 | 174 | let vanillaNestedInitialized = false 175 | const initOnce = () => { 176 | if (!vanillaNestedInitialized) { 177 | vanillaNestedInitialized = true 178 | initVanillaNested() 179 | } 180 | } 181 | 182 | if (["complete", "interactive"].includes(document.readyState)) { 183 | // if DOMContentLoaded was already fired 184 | initOnce() 185 | } else { 186 | // else wait for it 187 | document.addEventListener("DOMContentLoaded", () => initOnce()) 188 | } 189 | })() 190 | -------------------------------------------------------------------------------- /github-assets/sample.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/github-assets/sample.gif -------------------------------------------------------------------------------- /lib/vanilla_nested.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'vanilla_nested/view_helpers' 4 | 5 | module VanillaNested 6 | class Engine < ::Rails::Engine 7 | initializer 'vanilla_nested.initialize' do |_app| 8 | ActiveSupport.on_load :action_view do 9 | ActionView::Base.send :include, VanillaNested::ViewHelpers 10 | end 11 | end 12 | 13 | initializer "vanilla_nested.assets" do 14 | if Rails.application.config.respond_to?(:assets) 15 | Rails.application.config.assets.precompile += %w( vanilla_nested.js ) 16 | end 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/vanilla_nested/view_helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module VanillaNested 4 | module ViewHelpers 5 | # @param form [FormBuild] builder on a "form_for" block 6 | # @param association [Symbol] name of the association 7 | # @param container_selector [String] selector of the element to insert the fields 8 | # @param link_text [String, nil] text to use for the link tag 9 | # @param link_classes [String] space separated classes for the link tag 10 | # @param insert_method [:append, :prepend] tells javascript if the new fields should be appended or prepended to the container 11 | # @param partial_form_variable [String, Symbol] name of the variable that represents the form builder inside the fields partial 12 | # @param partial_locals [Hash] extra params that should be send to the partial 13 | # @param tag [String] HTML tag to use for the html generated, defaults to and `a` tag 14 | # @param link_content [Block] block of code for the link content 15 | # @param tag_attributes [Hash] hash with attribute,value pairs for the html tag 16 | # @return [String] link tag 17 | def link_to_add_nested(form, association, container_selector, link_text: nil, link_classes: '', insert_method: :append, partial: nil, partial_form_variable: :form, partial_locals: {}, tag: 'a', tag_attributes: {}, &link_content) 18 | association_class = form.object.class.reflections[association.to_s].klass 19 | object = association_class.new 20 | 21 | partial_name = partial || "#{association_class.name.underscore}_fields" 22 | 23 | html = capture do 24 | form.fields_for association, object, child_index: '_idx_placeholder_' do |ff| 25 | render partial: partial_name, locals: { partial_form_variable => ff }.merge(partial_locals) 26 | end 27 | end 28 | 29 | method_for_insert = %i[append prepend].include?(insert_method.to_sym) ? insert_method : :append 30 | 31 | classes = "vanilla-nested-add #{link_classes}" 32 | data = { 33 | 'container-selector': container_selector, 34 | 'html': html, 35 | 'method-for-insert': method_for_insert 36 | } 37 | 38 | nested_options = form.object.class.nested_attributes_options[association.to_sym] 39 | data['limit'] = nested_options[:limit] if nested_options[:limit] 40 | 41 | attributes = tag_attributes 42 | attributes[:class] = "#{attributes.fetch(:class, '')} #{classes}" 43 | attributes[:data] = attributes.fetch(:data, {}).merge(data) 44 | 45 | content_tag(tag, attributes) do 46 | if block_given? 47 | yield link_content 48 | else 49 | link_text || "Add #{association_class.model_name}" 50 | end 51 | end 52 | end 53 | 54 | # @param form [FormBuilder] builder on a "form_for" block 55 | # @param link_text [String, nil] text for the link, defaults to 'X' 56 | # @param fields_wrapper_selector [String] selector for the wrapper of the fields, must be an ancestor 57 | # @param undo_link_timeout [Integer] time until undo timeouts 58 | # @param undo_link_text [String] text to show as "undo" 59 | # @param undo_link_classes [String] space separated list of classes for the "undo" link 60 | # @param ulink_classes [String] space separated list of classes for the "x" link 61 | # @param tag [String] HTML tag to use for the html generated, defaults to and `a` tag 62 | # @param link_content [Block] block of code for the link content 63 | # @param tag_attributes [Hash] hash with attribute,value pairs for the html tag 64 | # @return [String] hidden field and link tag 65 | def link_to_remove_nested(form, link_text: 'X', fields_wrapper_selector: nil, undo_link_timeout: nil, undo_link_text: 'Undo', undo_link_classes: '', link_classes: '', tag: 'a', tag_attributes: {}, &link_content) 66 | data = { 67 | 'fields-wrapper-selector': fields_wrapper_selector, 68 | 'undo-timeout': undo_link_timeout, 69 | 'undo-text': undo_link_text, 70 | 'undo-link-classes': undo_link_classes 71 | } 72 | 73 | classes = "vanilla-nested-remove #{link_classes}" 74 | 75 | attributes = tag_attributes 76 | attributes[:class] = "#{attributes.fetch(:class, '')} #{classes}" 77 | attributes[:data] = attributes.fetch(:data, {}).merge(data) 78 | 79 | capture do 80 | concat form.hidden_field(:_destroy, value: 0) 81 | concat( 82 | content_tag(tag, attributes) do 83 | if block_given? 84 | yield link_content 85 | else 86 | link_text.html_safe 87 | end 88 | end 89 | ) 90 | end 91 | end 92 | end 93 | end 94 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vanilla-nested", 3 | "version": "1.7.0", 4 | "description": "Dynamic nested form for Ruby On Rails", 5 | "main": "app/assets/javascripts/vanilla_nested.js", 6 | "repository": "git@github.com:arielj/vanilla-nested.git", 7 | "author": "Ariel Juodziukynas ", 8 | "license": "MIT", 9 | "private": false, 10 | "files": [ 11 | "app/" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore the default SQLite database. 11 | /db/*.sqlite3 12 | /db/*.sqlite3-* 13 | 14 | # Ignore all logfiles and tempfiles. 15 | /log/* 16 | /tmp/* 17 | !/log/.keep 18 | !/tmp/.keep 19 | 20 | # Ignore pidfiles, but keep the directory. 21 | /tmp/pids/* 22 | !/tmp/pids/ 23 | !/tmp/pids/.keep 24 | 25 | # Ignore uploaded files in development. 26 | /storage/* 27 | !/storage/.keep 28 | /tmp/storage/* 29 | !/tmp/storage/ 30 | !/tmp/storage/.keep 31 | 32 | /public/assets 33 | 34 | # Ignore master key for decrypting credentials and more. 35 | /config/master.key 36 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/.ruby-version: -------------------------------------------------------------------------------- 1 | ruby-3.0.2 2 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | git_source(:github) { |repo| "https://github.com/#{repo}.git" } 3 | 4 | # Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main" 5 | gem "rails", "~> 7.0.1" 6 | 7 | # The original asset pipeline for Rails [https://github.com/rails/sprockets-rails] 8 | gem "sprockets-rails" 9 | 10 | # Use sqlite3 as the database for Active Record 11 | gem "sqlite3", "~> 1.4" 12 | 13 | # Use the Puma web server [https://github.com/puma/puma] 14 | gem "puma", "~> 5.0" 15 | 16 | # Use JavaScript with ESM import maps [https://github.com/rails/importmap-rails] 17 | gem "importmap-rails" 18 | 19 | # Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev] 20 | gem "turbo-rails" 21 | 22 | # Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev] 23 | gem "stimulus-rails" 24 | 25 | # Build JSON APIs with ease [https://github.com/rails/jbuilder] 26 | gem "jbuilder" 27 | 28 | # Use Redis adapter to run Action Cable in production 29 | gem "redis", "~> 4.0" 30 | 31 | # Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis] 32 | # gem "kredis" 33 | 34 | # Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword] 35 | # gem "bcrypt", "~> 3.1.7" 36 | 37 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem 38 | gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ] 39 | 40 | # Reduces boot times through caching; required in config/boot.rb 41 | gem "bootsnap", require: false 42 | 43 | # Use Sass to process CSS 44 | # gem "sassc-rails" 45 | 46 | # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] 47 | # gem "image_processing", "~> 1.2" 48 | 49 | gem 'vanilla_nested', path: '../../' 50 | 51 | group :development, :test do 52 | # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem 53 | gem "debug", platforms: %i[ mri mingw x64_mingw ] 54 | end 55 | 56 | group :development do 57 | # Use console on exceptions pages [https://github.com/rails/web-console] 58 | gem "web-console" 59 | 60 | # Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler] 61 | # gem "rack-mini-profiler" 62 | 63 | # Speed up commands on slow machines / big apps [https://github.com/rails/spring] 64 | # gem "spring" 65 | end 66 | 67 | group :test do 68 | # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing] 69 | gem "capybara" 70 | gem "selenium-webdriver" 71 | gem "webdrivers" 72 | end 73 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | This README would normally document whatever steps are necessary to get the 4 | application up and running. 5 | 6 | Things you may want to cover: 7 | 8 | * Ruby version 9 | 10 | * System dependencies 11 | 12 | * Configuration 13 | 14 | * Database creation 15 | 16 | * Database initialization 17 | 18 | * How to run the test suite 19 | 20 | * Services (job queues, cache servers, search engines, etc.) 21 | 22 | * Deployment instructions 23 | 24 | * ... 25 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative "config/application" 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link_tree ../images 2 | //= link_directory ../stylesheets .css 3 | //= link_tree ../../javascript .js 4 | //= link_tree ../../../vendor/javascript .js 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/app/assets/images/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's 6 | * vendor/assets/stylesheets directory can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any other CSS 10 | * files in this directory. Styles in this file should be added after the last require_* statement. 11 | * It is generally better to create a new file per style scope. 12 | * 13 | *= require_tree . 14 | *= require_self 15 | */ 16 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/channels/application_cable/channel.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Channel < ActionCable::Channel::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/channels/application_cable/connection.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Connection < ActionCable::Connection::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | end 3 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/controllers/users_controller.rb: -------------------------------------------------------------------------------- 1 | class UsersController < ApplicationController 2 | before_action :new_user 3 | 4 | def new 5 | end 6 | 7 | def new_with_custom_link_tag 8 | end 9 | 10 | def new_with_undo 11 | end 12 | 13 | def new_with_attributes_on_link_tag 14 | end 15 | 16 | def new_using_turbo 17 | render template: 'users/new', layout: "turbo" 18 | end 19 | 20 | private 21 | def new_user 22 | @user = User.new 23 | @user.pets.build 24 | end 25 | end -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/javascript/application.js: -------------------------------------------------------------------------------- 1 | // Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails 2 | import "@hotwired/turbo-rails"; 3 | import "controllers"; 4 | 5 | import "vanilla-nested"; 6 | 7 | document.addEventListener("vanilla-nested:fields-limit-reached", () => { 8 | document 9 | .getElementById("pets") 10 | .insertAdjacentHTML("afterbegin", "Limit reached"); 11 | }); 12 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/javascript/controllers/application.js: -------------------------------------------------------------------------------- 1 | import { Application } from "@hotwired/stimulus" 2 | 3 | const application = Application.start() 4 | 5 | // Configure Stimulus development experience 6 | application.debug = false 7 | window.Stimulus = application 8 | 9 | export { application } 10 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/javascript/controllers/hello_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from "@hotwired/stimulus" 2 | 3 | export default class extends Controller { 4 | connect() { 5 | this.element.textContent = "Hello World!" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/javascript/controllers/index.js: -------------------------------------------------------------------------------- 1 | // Import and register all your controllers from the importmap under controllers/* 2 | 3 | import { application } from "controllers/application" 4 | 5 | // Eager load all controllers defined in the import map under controllers/**/*_controller 6 | import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading" 7 | eagerLoadControllersFrom("controllers", application) 8 | 9 | // Lazy load controllers as they appear in the DOM (remember not to preload controllers in import map!) 10 | // import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading" 11 | // lazyLoadControllersFrom("controllers", application) 12 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | # Automatically retry jobs that encountered a deadlock 3 | # retry_on ActiveRecord::Deadlocked 4 | 5 | # Most jobs are safe to ignore if the underlying records are no longer available 6 | # discard_on ActiveJob::DeserializationError 7 | end 8 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | class ApplicationMailer < ActionMailer::Base 2 | default from: "from@example.com" 3 | layout "mailer" 4 | end 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | primary_abstract_class 3 | end 4 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/app/models/concerns/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/models/pet.rb: -------------------------------------------------------------------------------- 1 | class Pet < ApplicationRecord 2 | belongs_to :user 3 | end -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/models/user.rb: -------------------------------------------------------------------------------- 1 | class User < ApplicationRecord 2 | has_many :pets 3 | accepts_nested_attributes_for :pets, limit: 3 4 | end 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | VanillaNestedTestRails7 5 | 6 | <%= csrf_meta_tags %> 7 | <%= csp_meta_tag %> 8 | 9 | <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> 10 | <%= javascript_importmap_tags %> 11 | 12 | 13 | 14 | <%= yield %> 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/layouts/turbo.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | VanillaNestedTests 5 | <%= csrf_meta_tags %> 6 | <%= csp_meta_tag %> 7 | 8 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> 9 | <%= javascript_pack_tag 'application_turbo', 'data-turbolinks-track': 'reload' %> 10 | 11 | 12 | 13 | <%= yield %> 14 | 15 | 16 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/users/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for user do |form| %> 2 | <%= form.label :name %> 3 | <%= form.text_field :name %> 4 | 5 | <%= link_to_add_nested(form, :pets, '#pets') do %> 6 | Add Pet 7 | <% end %> 8 |

Pets

9 |
10 |

The limit is 3, configured in the model:

11 | <%= form.fields_for :pets do |pet_f| %> 12 | <%= render 'pet_fields', form: pet_f %> 13 | <% end %> 14 |
15 | <% end %> -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/users/_form_with_attributes_on_link_tag.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for user do |form| %> 2 | <%= form.label :name %> 3 | <%= form.text_field :name, tabindex: 1 %> 4 | 5 | <%= link_to_add_nested(form, :pets, '#pets', link_text: '+', tag_attributes: {title: "Add Pet", data: {some_data: 'is preserved'}}, partial: 'pet_fields_with_attributes_on_link_tag') %> 6 | 7 |

Pets

8 |
9 | <%= form.fields_for :pets do |pet_f| %> 10 | <%= render 'pet_fields_with_attributes_on_link_tag', form: pet_f %> 11 | <% end %> 12 |
13 | <% end %> -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/users/_form_with_custom_link_tag.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for user do |form| %> 2 | <%= form.label :name %> 3 | <%= form.text_field :name %> 4 | 5 | <%= link_to_add_nested(form, :pets, '#pets', tag: 'span', partial: 'pet_fields_with_custom_link_tag') do %> 6 | Add Pet 7 | <% end %> 8 |

Pets

9 |
10 | <%= form.fields_for :pets do |pet_f| %> 11 | <%= render 'pet_fields_with_custom_link_tag', form: pet_f %> 12 | <% end %> 13 |
14 | <% end %> -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/users/_form_with_undo.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for user do |form| %> 2 | <%= form.label :name %> 3 | <%= form.text_field :name %> 4 | 5 | <%= link_to_add_nested(form, :pets, '#pets', partial: 'pet_fields_with_undo') do %> 6 | Add Pet 7 | <% end %> 8 |

Pets

9 |
10 | <%= form.fields_for :pets do |pet_f| %> 11 | <%= render 'pet_fields_with_undo', form: pet_f %> 12 | <% end %> 13 |
14 | <% end %> -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/users/_pet_fields.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= form.label :name %> 3 | <%= form.text_field :name %> 4 | <%= form.label :color %> 5 | <%= form.text_field :color %> 6 | <%= link_to_remove_nested(form) do %> 7 | 8 | X 9 | 10 | <% end %> 11 |
-------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/users/_pet_fields_with_attributes_on_link_tag.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= form.label :name %> 3 | <%= form.text_field :name, tabindex: 2 %> 4 | <%= form.label :color %> 5 | <%= form.text_field :color, tabindex: 2 %> 6 | <%= link_to_remove_nested(form, tag: 'button', link_text: 'X', tag_attributes: {tabindex: "10"}) %> 7 |
-------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/users/_pet_fields_with_custom_link_tag.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= form.label :name %> 3 | <%= form.text_field :name %> 4 | <%= form.label :color %> 5 | <%= form.text_field :color %> 6 | <%= link_to_remove_nested(form, tag: 'div') do %> 7 | 8 | X 9 | 10 | <% end %> 11 |
-------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/users/_pet_fields_with_undo.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= form.label :name %> 3 | <%= form.text_field :name %> 4 | <%= form.label :color %> 5 | <%= form.text_field :color %> 6 | <%= link_to_remove_nested(form, undo_link_timeout: 400) do %> 7 | 8 | X 9 | 10 | <% end %> 11 |
-------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/users/index.html.erb: -------------------------------------------------------------------------------- 1 | <%= link_to 'New User', new_user_path %> 2 |
3 | <%= link_to 'New User with custom tags', new_with_custom_link_tag_users_path %> 4 |
5 | <%= link_to 'New User with undo', new_with_undo_users_path %> 6 |
7 | <%= link_to 'New User with attributes on links', new_with_attributes_on_link_tag_users_path %> -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/users/new.html.erb: -------------------------------------------------------------------------------- 1 | <%= render partial: 'form', locals: {user: @user} %> 2 | <%= link_to 'Back', users_path %> -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/users/new_with_attributes_on_link_tag.html.erb: -------------------------------------------------------------------------------- 1 | <%= render partial: 'form_with_attributes_on_link_tag', locals: {user: @user} %> 2 | <%= link_to 'Back', users_path %> -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/users/new_with_custom_link_tag.html.erb: -------------------------------------------------------------------------------- 1 | <%= render partial: 'form_with_custom_link_tag', locals: {user: @user} %> 2 | <%= link_to 'Back', users_path %> -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/app/views/users/new_with_undo.html.erb: -------------------------------------------------------------------------------- 1 | <%= render partial: 'form_with_undo', locals: {user: @user} %> 2 | <%= link_to 'Back', users_path %> -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'bundle' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "rubygems" 12 | 13 | m = Module.new do 14 | module_function 15 | 16 | def invoked_as_script? 17 | File.expand_path($0) == File.expand_path(__FILE__) 18 | end 19 | 20 | def env_var_version 21 | ENV["BUNDLER_VERSION"] 22 | end 23 | 24 | def cli_arg_version 25 | return unless invoked_as_script? # don't want to hijack other binstubs 26 | return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` 27 | bundler_version = nil 28 | update_index = nil 29 | ARGV.each_with_index do |a, i| 30 | if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN 31 | bundler_version = a 32 | end 33 | next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ 34 | bundler_version = $1 35 | update_index = i 36 | end 37 | bundler_version 38 | end 39 | 40 | def gemfile 41 | gemfile = ENV["BUNDLE_GEMFILE"] 42 | return gemfile if gemfile && !gemfile.empty? 43 | 44 | File.expand_path("../../Gemfile", __FILE__) 45 | end 46 | 47 | def lockfile 48 | lockfile = 49 | case File.basename(gemfile) 50 | when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) 51 | else "#{gemfile}.lock" 52 | end 53 | File.expand_path(lockfile) 54 | end 55 | 56 | def lockfile_version 57 | return unless File.file?(lockfile) 58 | lockfile_contents = File.read(lockfile) 59 | return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ 60 | Regexp.last_match(1) 61 | end 62 | 63 | def bundler_requirement 64 | @bundler_requirement ||= 65 | env_var_version || cli_arg_version || 66 | bundler_requirement_for(lockfile_version) 67 | end 68 | 69 | def bundler_requirement_for(version) 70 | return "#{Gem::Requirement.default}.a" unless version 71 | 72 | bundler_gem_version = Gem::Version.new(version) 73 | 74 | requirement = bundler_gem_version.approximate_recommendation 75 | 76 | return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0") 77 | 78 | requirement += ".a" if bundler_gem_version.prerelease? 79 | 80 | requirement 81 | end 82 | 83 | def load_bundler! 84 | ENV["BUNDLE_GEMFILE"] ||= gemfile 85 | 86 | activate_bundler 87 | end 88 | 89 | def activate_bundler 90 | gem_error = activation_error_handling do 91 | gem "bundler", bundler_requirement 92 | end 93 | return if gem_error.nil? 94 | require_error = activation_error_handling do 95 | require "bundler/version" 96 | end 97 | return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) 98 | warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`" 99 | exit 42 100 | end 101 | 102 | def activation_error_handling 103 | yield 104 | nil 105 | rescue StandardError, LoadError => e 106 | e 107 | end 108 | end 109 | 110 | m.load_bundler! 111 | 112 | if m.invoked_as_script? 113 | load Gem.bin_path("bundler", "bundle") 114 | end 115 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/bin/importmap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require_relative "../config/application" 4 | require "importmap/commands" 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path("../config/application", __dir__) 3 | require_relative "../config/boot" 4 | require "rails/commands" 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative "../config/boot" 3 | require "rake" 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "fileutils" 3 | 4 | # path to your application root. 5 | APP_ROOT = File.expand_path("..", __dir__) 6 | 7 | def system!(*args) 8 | system(*args) || abort("\n== Command #{args} failed ==") 9 | end 10 | 11 | FileUtils.chdir APP_ROOT do 12 | # This script is a way to set up or update your development environment automatically. 13 | # This script is idempotent, so that you can run it at any time and get an expectable outcome. 14 | # Add necessary setup steps to this file. 15 | 16 | puts "== Installing dependencies ==" 17 | system! "gem install bundler --conservative" 18 | system("bundle check") || system!("bundle install") 19 | 20 | # puts "\n== Copying sample files ==" 21 | # unless File.exist?("config/database.yml") 22 | # FileUtils.cp "config/database.yml.sample", "config/database.yml" 23 | # end 24 | 25 | puts "\n== Preparing database ==" 26 | system! "bin/rails db:prepare" 27 | 28 | puts "\n== Removing old logs and tempfiles ==" 29 | system! "bin/rails log:clear tmp:clear" 30 | 31 | puts "\n== Restarting application server ==" 32 | system! "bin/rails restart" 33 | end 34 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative "config/environment" 4 | 5 | run Rails.application 6 | Rails.application.load_server 7 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/application.rb: -------------------------------------------------------------------------------- 1 | require_relative "boot" 2 | 3 | require "rails/all" 4 | 5 | # Require the gems listed in Gemfile, including any gems 6 | # you've limited to :test, :development, or :production. 7 | Bundler.require(*Rails.groups) 8 | 9 | module VanillaNestedTestRails7 10 | class Application < Rails::Application 11 | # Initialize configuration defaults for originally generated Rails version. 12 | config.load_defaults 7.0 13 | 14 | # Configuration for the application, engines, and railties goes here. 15 | # 16 | # These settings can be overridden in specific environments using the files 17 | # in config/environments, which are processed later. 18 | # 19 | # config.time_zone = "Central Time (US & Canada)" 20 | # config.eager_load_paths << Rails.root.join("extras") 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) 2 | 3 | require "bundler/setup" # Set up gems listed in the Gemfile. 4 | require "bootsnap/setup" # Speed up boot time by caching expensive operations. 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: redis 3 | url: redis://localhost:6379/1 4 | 5 | test: 6 | adapter: test 7 | 8 | production: 9 | adapter: redis 10 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 11 | channel_prefix: VanillaNestedTestRails7_production 12 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/credentials.yml.enc: -------------------------------------------------------------------------------- 1 | 3GLssJALiDajV2ERBoKiAF1fT5YQN/KJNBnOY/Z3RMTYUEoekz6IE5hfDNi12hWx5k68hm5tDDO5/NHkjfWMwRc1Ajuo69m20yDwbdG2DoWNhUKjpn6XOmjJ1TFVjvXn1HmzdD0l0fSsGHHr1GbMg/meiydCwCAeg1Yc5e6hsKjkbnDT9kgCwx12UNoMXZnJ5k34IswJToWy2bAT09K/BRuyNG7U/8kNWEiP3JlYJtrbjFeJe9NmChevMudoKEKv3qIrKYEOeLqJ5NkClPnEsPSnOJZ3diQXnoBbtwbe3sfA45KrpWBqxvH9f+qYIFcaSQrUcVWAJcbcWN3o+7if2BLFaw6IlPFcZ56kC0qHbbwDRPl7y7mYplmJGpK/Gn1N38JHIqd5eF0sKZuqjXhFuMFDFdwlSdzBgyqZ--0rmH7stSAXUW//52--if1Zwu6cYRkYre3TIqZU/A== -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite. Versions 3.8.0 and up are supported. 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem "sqlite3" 6 | # 7 | default: &default 8 | adapter: sqlite3 9 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 10 | timeout: 5000 11 | 12 | development: 13 | <<: *default 14 | database: db/development.sqlite3 15 | 16 | # Warning: The database defined as "test" will be erased and 17 | # re-generated from your development database when you run "rake". 18 | # Do not set this db to the same as development or production. 19 | test: 20 | <<: *default 21 | database: db/test.sqlite3 22 | 23 | production: 24 | <<: *default 25 | database: db/production.sqlite3 26 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative "application" 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/environments/development.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | Rails.application.configure do 4 | # Settings specified here will take precedence over those in config/application.rb. 5 | 6 | # In the development environment your application's code is reloaded any time 7 | # it changes. This slows down response time but is perfect for development 8 | # since you don't have to restart the web server when you make code changes. 9 | config.cache_classes = false 10 | 11 | # Do not eager load code on boot. 12 | config.eager_load = false 13 | 14 | # Show full error reports. 15 | config.consider_all_requests_local = true 16 | 17 | # Enable server timing 18 | config.server_timing = true 19 | 20 | # Enable/disable caching. By default caching is disabled. 21 | # Run rails dev:cache to toggle caching. 22 | if Rails.root.join("tmp/caching-dev.txt").exist? 23 | config.action_controller.perform_caching = true 24 | config.action_controller.enable_fragment_cache_logging = true 25 | 26 | config.cache_store = :memory_store 27 | config.public_file_server.headers = { 28 | "Cache-Control" => "public, max-age=#{2.days.to_i}" 29 | } 30 | else 31 | config.action_controller.perform_caching = false 32 | 33 | config.cache_store = :null_store 34 | end 35 | 36 | # Store uploaded files on the local file system (see config/storage.yml for options). 37 | config.active_storage.service = :local 38 | 39 | # Don't care if the mailer can't send. 40 | config.action_mailer.raise_delivery_errors = false 41 | 42 | config.action_mailer.perform_caching = false 43 | 44 | # Print deprecation notices to the Rails logger. 45 | config.active_support.deprecation = :log 46 | 47 | # Raise exceptions for disallowed deprecations. 48 | config.active_support.disallowed_deprecation = :raise 49 | 50 | # Tell Active Support which deprecation messages to disallow. 51 | config.active_support.disallowed_deprecation_warnings = [] 52 | 53 | # Raise an error on page load if there are pending migrations. 54 | config.active_record.migration_error = :page_load 55 | 56 | # Highlight code that triggered database queries in logs. 57 | config.active_record.verbose_query_logs = true 58 | 59 | # Suppress logger output for asset requests. 60 | config.assets.quiet = true 61 | 62 | # Raises error for missing translations. 63 | # config.i18n.raise_on_missing_translations = true 64 | 65 | # Annotate rendered view with file names. 66 | # config.action_view.annotate_rendered_view_with_filenames = true 67 | 68 | # Uncomment if you wish to allow Action Cable access from any origin. 69 | # config.action_cable.disable_request_forgery_protection = true 70 | end 71 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/environments/production.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | Rails.application.configure do 4 | # Settings specified here will take precedence over those in config/application.rb. 5 | 6 | # Code is not reloaded between requests. 7 | config.cache_classes = true 8 | 9 | # Eager load code on boot. This eager loads most of Rails and 10 | # your application in memory, allowing both threaded web servers 11 | # and those relying on copy on write to perform better. 12 | # Rake tasks automatically ignore this option for performance. 13 | config.eager_load = true 14 | 15 | # Full error reports are disabled and caching is turned on. 16 | config.consider_all_requests_local = false 17 | config.action_controller.perform_caching = true 18 | 19 | # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] 20 | # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). 21 | # config.require_master_key = true 22 | 23 | # Disable serving static files from the `/public` folder by default since 24 | # Apache or NGINX already handles this. 25 | config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? 26 | 27 | # Compress CSS using a preprocessor. 28 | # config.assets.css_compressor = :sass 29 | 30 | # Do not fallback to assets pipeline if a precompiled asset is missed. 31 | config.assets.compile = false 32 | 33 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 34 | # config.asset_host = "http://assets.example.com" 35 | 36 | # Specifies the header that your server uses for sending files. 37 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache 38 | # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX 39 | 40 | # Store uploaded files on the local file system (see config/storage.yml for options). 41 | config.active_storage.service = :local 42 | 43 | # Mount Action Cable outside main process or domain. 44 | # config.action_cable.mount_path = nil 45 | # config.action_cable.url = "wss://example.com/cable" 46 | # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ] 47 | 48 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 49 | # config.force_ssl = true 50 | 51 | # Include generic and useful information about system operation, but avoid logging too much 52 | # information to avoid inadvertent exposure of personally identifiable information (PII). 53 | config.log_level = :info 54 | 55 | # Prepend all log lines with the following tags. 56 | config.log_tags = [ :request_id ] 57 | 58 | # Use a different cache store in production. 59 | # config.cache_store = :mem_cache_store 60 | 61 | # Use a real queuing backend for Active Job (and separate queues per environment). 62 | # config.active_job.queue_adapter = :resque 63 | # config.active_job.queue_name_prefix = "VanillaNestedTestRails7_production" 64 | 65 | config.action_mailer.perform_caching = false 66 | 67 | # Ignore bad email addresses and do not raise email delivery errors. 68 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 69 | # config.action_mailer.raise_delivery_errors = false 70 | 71 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 72 | # the I18n.default_locale when a translation cannot be found). 73 | config.i18n.fallbacks = true 74 | 75 | # Don't log any deprecations. 76 | config.active_support.report_deprecations = false 77 | 78 | # Use default logging formatter so that PID and timestamp are not suppressed. 79 | config.log_formatter = ::Logger::Formatter.new 80 | 81 | # Use a different logger for distributed setups. 82 | # require "syslog/logger" 83 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name") 84 | 85 | if ENV["RAILS_LOG_TO_STDOUT"].present? 86 | logger = ActiveSupport::Logger.new(STDOUT) 87 | logger.formatter = config.log_formatter 88 | config.logger = ActiveSupport::TaggedLogging.new(logger) 89 | end 90 | 91 | # Do not dump schema after migrations. 92 | config.active_record.dump_schema_after_migration = false 93 | end 94 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/environments/test.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | # The test environment is used exclusively to run your application's 4 | # test suite. You never need to work with it otherwise. Remember that 5 | # your test database is "scratch space" for the test suite and is wiped 6 | # and recreated between test runs. Don't rely on the data there! 7 | 8 | Rails.application.configure do 9 | # Settings specified here will take precedence over those in config/application.rb. 10 | 11 | # Turn false under Spring and add config.action_view.cache_template_loading = true. 12 | config.cache_classes = true 13 | 14 | # Eager loading loads your whole application. When running a single test locally, 15 | # this probably isn't necessary. It's a good idea to do in a continuous integration 16 | # system, or in some way before deploying your code. 17 | config.eager_load = ENV["CI"].present? 18 | 19 | # Configure public file server for tests with Cache-Control for performance. 20 | config.public_file_server.enabled = true 21 | config.public_file_server.headers = { 22 | "Cache-Control" => "public, max-age=#{1.hour.to_i}" 23 | } 24 | 25 | # Show full error reports and disable caching. 26 | config.consider_all_requests_local = true 27 | config.action_controller.perform_caching = false 28 | config.cache_store = :null_store 29 | 30 | # Raise exceptions instead of rendering exception templates. 31 | config.action_dispatch.show_exceptions = false 32 | 33 | # Disable request forgery protection in test environment. 34 | config.action_controller.allow_forgery_protection = false 35 | 36 | # Store uploaded files on the local file system in a temporary directory. 37 | config.active_storage.service = :test 38 | 39 | config.action_mailer.perform_caching = false 40 | 41 | # Tell Action Mailer not to deliver emails to the real world. 42 | # The :test delivery method accumulates sent emails in the 43 | # ActionMailer::Base.deliveries array. 44 | config.action_mailer.delivery_method = :test 45 | 46 | # Print deprecation notices to the stderr. 47 | config.active_support.deprecation = :stderr 48 | 49 | # Raise exceptions for disallowed deprecations. 50 | config.active_support.disallowed_deprecation = :raise 51 | 52 | # Tell Active Support which deprecation messages to disallow. 53 | config.active_support.disallowed_deprecation_warnings = [] 54 | 55 | # Raises error for missing translations. 56 | # config.i18n.raise_on_missing_translations = true 57 | 58 | # Annotate rendered view with file names. 59 | # config.action_view.annotate_rendered_view_with_filenames = true 60 | end 61 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/importmap.rb: -------------------------------------------------------------------------------- 1 | # Pin npm packages by running ./bin/importmap 2 | 3 | pin "application", preload: true 4 | pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true 5 | pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true 6 | pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true 7 | pin "vanilla-nested", to: "vanilla_nested.js", preload: true 8 | pin_all_from "app/javascript/controllers", under: "controllers" 9 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = "1.0" 5 | 6 | # Add additional assets to the asset load path. 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | 9 | # Precompile additional assets. 10 | # application.js, application.css, and all non-JS/CSS in the app/assets 11 | # folder are already added. 12 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 13 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/initializers/content_security_policy.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Define an application-wide content security policy 4 | # For further information see the following documentation 5 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy 6 | 7 | # Rails.application.configure do 8 | # config.content_security_policy do |policy| 9 | # policy.default_src :self, :https 10 | # policy.font_src :self, :https, :data 11 | # policy.img_src :self, :https, :data 12 | # policy.object_src :none 13 | # policy.script_src :self, :https 14 | # policy.style_src :self, :https 15 | # # Specify URI for violation reports 16 | # # policy.report_uri "/csp-violation-report-endpoint" 17 | # end 18 | # 19 | # # Generate session nonces for permitted importmap and inline scripts 20 | # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } 21 | # config.content_security_policy_nonce_directives = %w(script-src) 22 | # 23 | # # Report CSP violations to a specified URI. See: 24 | # # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only 25 | # # config.content_security_policy_report_only = true 26 | # end 27 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [ 5 | :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn 6 | ] 7 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, "\\1en" 8 | # inflect.singular /^(ox)en/i, "\\1" 9 | # inflect.irregular "person", "people" 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym "RESTful" 16 | # end 17 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/initializers/permissions_policy.rb: -------------------------------------------------------------------------------- 1 | # Define an application-wide HTTP permissions policy. For further 2 | # information see https://developers.google.com/web/updates/2018/06/feature-policy 3 | # 4 | # Rails.application.config.permissions_policy do |f| 5 | # f.camera :none 6 | # f.gyroscope :none 7 | # f.microphone :none 8 | # f.usb :none 9 | # f.fullscreen :self 10 | # f.payment :self, "https://secure.example.com" 11 | # end 12 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t "hello" 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t("hello") %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # The following keys must be escaped otherwise they will not be retrieved by 20 | # the default I18n backend: 21 | # 22 | # true, false, on, off, yes, no 23 | # 24 | # Instead, surround them with single quotes. 25 | # 26 | # en: 27 | # "true": "foo" 28 | # 29 | # To learn more, please read the Rails Internationalization guide 30 | # available at https://guides.rubyonrails.org/i18n.html. 31 | 32 | en: 33 | hello: "Hello world" 34 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/puma.rb: -------------------------------------------------------------------------------- 1 | # Puma can serve each request in a thread from an internal thread pool. 2 | # The `threads` method setting takes two numbers: a minimum and maximum. 3 | # Any libraries that use thread pools should be configured to match 4 | # the maximum value specified for Puma. Default is set to 5 threads for minimum 5 | # and maximum; this matches the default thread size of Active Record. 6 | # 7 | max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } 8 | min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } 9 | threads min_threads_count, max_threads_count 10 | 11 | # Specifies the `worker_timeout` threshold that Puma will use to wait before 12 | # terminating a worker in development environments. 13 | # 14 | worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development" 15 | 16 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000. 17 | # 18 | port ENV.fetch("PORT") { 3000 } 19 | 20 | # Specifies the `environment` that Puma will run in. 21 | # 22 | environment ENV.fetch("RAILS_ENV") { "development" } 23 | 24 | # Specifies the `pidfile` that Puma will use. 25 | pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } 26 | 27 | # Specifies the number of `workers` to boot in clustered mode. 28 | # Workers are forked web server processes. If using threads and workers together 29 | # the concurrency of the application would be max `threads` * `workers`. 30 | # Workers do not work on JRuby or Windows (both of which do not support 31 | # processes). 32 | # 33 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 } 34 | 35 | # Use the `preload_app!` method when specifying a `workers` number. 36 | # This directive tells Puma to first boot the application and load code 37 | # before forking the application. This takes advantage of Copy On Write 38 | # process behavior so workers use less memory. 39 | # 40 | # preload_app! 41 | 42 | # Allow puma to be restarted by `bin/rails restart` command. 43 | plugin :tmp_restart 44 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html 3 | resources :users do 4 | collection do 5 | get :new_with_custom_link_tag 6 | get :new_with_undo 7 | get :new_with_attributes_on_link_tag 8 | get :new_using_turbo 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join("tmp/storage") %> 4 | 5 | local: 6 | service: Disk 7 | root: <%= Rails.root.join("storage") %> 8 | 9 | # Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) 10 | # amazon: 11 | # service: S3 12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> 13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> 14 | # region: us-east-1 15 | # bucket: your_own_bucket-<%= Rails.env %> 16 | 17 | # Remember not to checkin your GCS keyfile to a repository 18 | # google: 19 | # service: GCS 20 | # project: your_project 21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> 22 | # bucket: your_own_bucket-<%= Rails.env %> 23 | 24 | # Use bin/rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) 25 | # microsoft: 26 | # service: AzureStorage 27 | # storage_account_name: your_account_name 28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> 29 | # container: your_container_name-<%= Rails.env %> 30 | 31 | # mirror: 32 | # service: Mirror 33 | # primary: local 34 | # mirrors: [ amazon, google, microsoft ] 35 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/db/migrate/20210220015506_create_users.rb: -------------------------------------------------------------------------------- 1 | class CreateUsers < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :users do |t| 4 | t.string :name 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/db/migrate/20210220015510_create_pets.rb: -------------------------------------------------------------------------------- 1 | class CreatePets < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :pets do |t| 4 | t.references :user 5 | t.string :name 6 | t.string :color 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/db/schema.rb: -------------------------------------------------------------------------------- 1 | # This file is auto-generated from the current state of the database. Instead 2 | # of editing this file, please use the migrations feature of Active Record to 3 | # incrementally modify your database, and then regenerate this schema definition. 4 | # 5 | # This file is the source Rails uses to define your schema when running `bin/rails 6 | # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to 7 | # be faster and is potentially less error prone than running all of your 8 | # migrations from scratch. Old migrations may fail to apply correctly if those 9 | # migrations use external dependencies or application code. 10 | # 11 | # It's strongly recommended that you check this file into your version control system. 12 | 13 | ActiveRecord::Schema[7.0].define(version: 2021_02_20_015510) do 14 | create_table "pets", force: :cascade do |t| 15 | t.integer "user_id" 16 | t.string "name" 17 | t.string "color" 18 | t.index ["user_id"], name: "index_pets_on_user_id" 19 | end 20 | 21 | create_table "users", force: :cascade do |t| 22 | t.string "name" 23 | end 24 | 25 | end 26 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). 3 | # 4 | # Examples: 5 | # 6 | # movies = Movie.create([{ name: "Star Wars" }, { name: "Lord of the Rings" }]) 7 | # Character.create(name: "Luke", movie: movies.first) 8 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/lib/assets/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/lib/tasks/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/log/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/public/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/public/apple-touch-icon.png -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/public/favicon.ico -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/public/robots.txt: -------------------------------------------------------------------------------- 1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/storage/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/storage/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/test/application_system_test_case.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class ApplicationSystemTestCase < ActionDispatch::SystemTestCase 4 | driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400] 5 | end 6 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/test/channels/application_cable/connection_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase 4 | # test "connects with cookies" do 5 | # cookies.signed[:user_id] = 42 6 | # 7 | # connect 8 | # 9 | # assert_equal connection.user_id, "42" 10 | # end 11 | end 12 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/test/controllers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/test/controllers/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/test/fixtures/files/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/test/fixtures/files/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/test/helpers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/test/helpers/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/test/integration/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/test/integration/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/test/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/test/mailers/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/test/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/test/models/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/test/system/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/test/system/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/test/system/html_tag_test.rb: -------------------------------------------------------------------------------- 1 | require "application_system_test_case" 2 | 3 | class HtmlTagTest < ApplicationSystemTestCase 4 | test "accepts custom tags for link_to_add/remove_nested" do 5 | visit new_with_custom_link_tag_users_path 6 | 7 | assert_selector '#new_user' 8 | 9 | assert_selector '.pet-fields', count: 1 10 | 11 | within '.pet-fields:nth-of-type(1)' do 12 | fill_in 'Name', with: 'Spike' 13 | end 14 | 15 | # wrapper is a SPAN tag 16 | find('span.vanilla-nested-add', text: 'Add Pet').click 17 | 18 | assert_selector '.pet-fields', count: 2 19 | 20 | within '.pet-fields:nth-of-type(2)' do 21 | fill_in 'Name', with: 'Marnie' 22 | end 23 | 24 | # wrapper is a DIV tag 25 | within '.pet-fields:nth-of-type(1)' do 26 | find('div.vanilla-nested-remove', text: 'X').click 27 | end 28 | end 29 | 30 | test "accepts attributes for the custom tags for link_to_add/remove_nested" do 31 | visit new_with_attributes_on_link_tag_users_path 32 | 33 | # 'add' wrapper has a title attribute 34 | # it also preserves data and classes attributes 35 | # tag_attributes: {title: "Add Pet", data: {some_data: 'is preserved'} 36 | find('.vanilla-nested-add[title="Add Pet"][data-some-data="is preserved"]', text: '+').click 37 | 38 | # wrapper has a tabindex 39 | # tag: 'button', tag_attributes: {tabindex: "10"} 40 | within '.pet-fields:nth-of-type(1)' do 41 | find('button.vanilla-nested-remove[tabindex="10"]', text: 'X').click 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/test/system/undo_test.rb: -------------------------------------------------------------------------------- 1 | require "application_system_test_case" 2 | 3 | class UndoTest < ApplicationSystemTestCase 4 | test "can undo" do 5 | visit new_with_undo_users_path 6 | 7 | assert_selector '#new_user' 8 | 9 | assert_selector '.pet-fields', count: 1 10 | 11 | within '.pet-fields:nth-of-type(1)' do 12 | fill_in 'Name', with: 'Spike' 13 | end 14 | 15 | find('.vanilla-nested-add', text: 'Add Pet').click 16 | 17 | assert_selector '.pet-fields', count: 2 18 | 19 | # test with fields added dynamically 20 | within '.pet-fields:nth-of-type(2)' do 21 | assert_selector '.vanilla-nested-undo', text: 'Undo', count: 0 22 | find('.vanilla-nested-remove', text: 'X').click 23 | 24 | # added the Undo button 25 | assert_selector '.vanilla-nested-undo', text: 'Undo', count: 1 26 | 27 | # click undo to stop the removal 28 | find('.vanilla-nested-undo', text: 'Undo').click() 29 | assert_selector '.vanilla-nested-undo', text: 'Undo', count: 0 30 | 31 | # click to remove for real 32 | find('.vanilla-nested-remove', text: 'X').click 33 | end 34 | 35 | sleep(0.5) # undo timeout is configured as 400ms 36 | 37 | assert_selector '.pet-fields', count: 1 38 | assert_selector '.pet-fields', visible: :hidden, count: 0 39 | 40 | # test with fields rendered server side 41 | within '.pet-fields:nth-of-type(1)' do 42 | assert_selector '.vanilla-nested-undo', text: 'Undo', count: 0 43 | find('.vanilla-nested-remove', text: 'X').click 44 | 45 | # added the Undo button 46 | assert_selector '.vanilla-nested-undo', text: 'Undo', count: 1 47 | 48 | # click undo to stop the removal 49 | find('.vanilla-nested-undo', text: 'Undo').click() 50 | assert_selector '.vanilla-nested-undo', text: 'Undo', count: 0 51 | 52 | # click to remove for real 53 | find('.vanilla-nested-remove', text: 'X').click 54 | end 55 | 56 | sleep(0.5) # undo timeout is configured as 400ms 57 | 58 | assert_selector '.pet-fields', count: 0 59 | assert_selector '.pet-fields', visible: :hidden, count: 1 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/test/system/vanilla_nested_test.rb: -------------------------------------------------------------------------------- 1 | require "application_system_test_case" 2 | 3 | class VanillaNestedTest < ApplicationSystemTestCase 4 | test "adds/removes fields" do 5 | visit users_path 6 | click_link 'New User' 7 | 8 | assert_selector '#new_user' 9 | 10 | # one field, not added by vanilla-nested 11 | assert_selector '.pet-fields:not(.added-by-vanilla-nested)', count: 1 12 | 13 | within '.pet-fields:nth-of-type(1)' do 14 | fill_in 'Name', with: 'Spike' 15 | end 16 | 17 | # adds 1 pet 18 | find('a.vanilla-nested-add', text: 'Add Pet').click 19 | 20 | assert_selector '.pet-fields', count: 2 21 | # one added and one not added by vanilla-nested 22 | assert_selector '.pet-fields:not(.added-by-vanilla-nested)', count: 1 23 | assert_selector '.pet-fields.added-by-vanilla-nested', count: 1 24 | 25 | within '.pet-fields:nth-of-type(2)' do 26 | fill_in 'Name', with: 'Marnie' 27 | end 28 | 29 | # removes first pet 30 | within '.pet-fields:nth-of-type(1)' do 31 | find('a.vanilla-nested-remove', text: 'X').click 32 | end 33 | 34 | # first pet is hidden 35 | assert_selector '.pet-fields', count: 1, visible: :hidden do |wrapper| 36 | assert_equal 1, wrapper.all('*', visible: :hidden).length 37 | destroy = wrapper.all('*', visible: :hidden).first 38 | assert_match /\[_destroy\]\z/, destroy.native.attribute('name') 39 | assert_equal '1', destroy.value 40 | end 41 | 42 | # second pet is visible 43 | assert_selector '.pet-fields', count: 1, visible: :visible do |wrapper| 44 | # verify it's the second one 45 | assert_equal 'Marnie', wrapper.first('input').value 46 | end 47 | 48 | within '.pet-fields:nth-of-type(2)' do 49 | find('a.vanilla-nested-remove', text: 'X').click 50 | end 51 | 52 | # second pet is not there anymore 53 | assert_selector '.pet-fields', count: 1, visible: :hidden 54 | end 55 | 56 | test "emits an event when the association limit is reached" do 57 | visit new_user_path 58 | 59 | assert_selector '#new_user' 60 | 61 | assert_selector '.pet-fields', count: 1 62 | 63 | find('a.vanilla-nested-add', text: 'Add Pet').click 64 | 65 | assert_selector '.pet-fields', count: 2 66 | 67 | assert_selector 'span', text: 'Limit reached', count: 0 68 | 69 | find('a.vanilla-nested-add', text: 'Add Pet').click 70 | 71 | assert_selector '.pet-fields', count: 3 72 | assert_selector 'span', text: 'Limit reached', count: 1 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/test/test_helper.rb: -------------------------------------------------------------------------------- 1 | ENV["RAILS_ENV"] ||= "test" 2 | require_relative "../config/environment" 3 | require "rails/test_help" 4 | 5 | class ActiveSupport::TestCase 6 | # Run tests in parallel with specified workers 7 | parallelize(workers: :number_of_processors) 8 | 9 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. 10 | fixtures :all 11 | 12 | # Add more helper methods to be used by all tests here... 13 | end 14 | -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/tmp/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/tmp/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/tmp/pids/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/tmp/pids/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/tmp/storage/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/tmp/storage/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/vendor/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/vendor/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTestRails7/vendor/javascript/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTestRails7/vendor/javascript/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults 2 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore the default SQLite database. 11 | /db/*.sqlite3 12 | /db/*.sqlite3-journal 13 | /db/*.sqlite3-* 14 | 15 | # Ignore all logfiles and tempfiles. 16 | /log/* 17 | /tmp/* 18 | 19 | # Ignore uploaded files in development. 20 | /storage/* 21 | 22 | /public/assets 23 | .byebug_history 24 | 25 | # Ignore master key for decrypting credentials and more. 26 | /config/master.key 27 | 28 | /public/packs 29 | /public/packs-test 30 | /node_modules 31 | /yarn-error.log 32 | yarn-debug.log* 33 | .yarn-integrity 34 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/.ruby-version: -------------------------------------------------------------------------------- 1 | ruby-2.6.5 2 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | git_source(:github) { |repo| "https://github.com/#{repo}.git" } 3 | 4 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 5 | gem 'rails', '~> 6.1.0' 6 | # Use sqlite3 as the database for Active Record 7 | gem 'sqlite3', '~> 1.4' 8 | # Use Puma as the app server 9 | gem 'puma', '~> 4.1' 10 | # Use SCSS for stylesheets 11 | gem 'sass-rails', '>= 6' 12 | # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker 13 | gem 'webpacker', '~> 4.0' 14 | # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks 15 | gem 'turbolinks', '~> 5' 16 | gem 'hotwire-rails' 17 | gem 'turbo-rails', '~> 0.8' 18 | 19 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 20 | gem 'jbuilder', '~> 2.7' 21 | # Use Redis adapter to run Action Cable in production 22 | gem 'redis', '~> 4.0' 23 | # Use Active Model has_secure_password 24 | # gem 'bcrypt', '~> 3.1.7' 25 | 26 | # Use Active Storage variant 27 | # gem 'image_processing', '~> 1.2' 28 | 29 | # Reduces boot times through caching; required in config/boot.rb 30 | gem 'bootsnap', '>= 1.4.2', require: false 31 | 32 | gem 'vanilla_nested', path: '../../' 33 | 34 | group :development, :test do 35 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console 36 | gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] 37 | end 38 | 39 | group :development do 40 | # Access an interactive console on exception pages or by calling 'console' anywhere in the code. 41 | gem 'web-console', '>= 3.3.0' 42 | gem 'listen', '>= 3.0.5', '< 3.2' 43 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 44 | gem 'spring' 45 | gem 'spring-watcher-listen', '~> 2.0.0' 46 | end 47 | 48 | group :test do 49 | # Adds support for Capybara system testing and selenium driver 50 | gem 'capybara', '>= 2.15' 51 | gem 'selenium-webdriver' 52 | # Easy installation and use of web drivers to run system tests with browsers 53 | gem 'webdrivers' 54 | end 55 | 56 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem 57 | gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] 58 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | This README would normally document whatever steps are necessary to get the 4 | application up and running. 5 | 6 | Things you may want to cover: 7 | 8 | * Ruby version 9 | 10 | * System dependencies 11 | 12 | * Configuration 13 | 14 | * Database creation 15 | 16 | * Database initialization 17 | 18 | * How to run the test suite 19 | 20 | * Services (job queues, cache servers, search engines, etc.) 21 | 22 | * Deployment instructions 23 | 24 | * ... 25 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative 'config/application' 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link_tree ../images 2 | //= link_directory ../stylesheets .css 3 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/app/assets/images/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's 6 | * vendor/assets/stylesheets directory can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS 10 | * files in this directory. Styles in this file should be added after the last require_* statement. 11 | * It is generally better to create a new file per style scope. 12 | * 13 | *= require_tree . 14 | *= require_self 15 | */ 16 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/channels/application_cable/channel.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Channel < ActionCable::Channel::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/channels/application_cable/connection.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Connection < ActionCable::Connection::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | end 3 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/controllers/users_controller.rb: -------------------------------------------------------------------------------- 1 | class UsersController < ApplicationController 2 | before_action :new_user 3 | 4 | def new 5 | end 6 | 7 | def new_with_custom_link_tag 8 | end 9 | 10 | def new_with_undo 11 | end 12 | 13 | def new_with_attributes_on_link_tag 14 | end 15 | 16 | def new_using_turbo 17 | render template: 'users/new', layout: "turbo" 18 | end 19 | 20 | private 21 | def new_user 22 | @user = User.new 23 | @user.pets.build 24 | end 25 | end -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/javascript/channels/consumer.js: -------------------------------------------------------------------------------- 1 | // Action Cable provides the framework to deal with WebSockets in Rails. 2 | // You can generate new channels where WebSocket features live using the `rails generate channel` command. 3 | 4 | import { createConsumer } from "@rails/actioncable" 5 | 6 | export default createConsumer() 7 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/javascript/channels/index.js: -------------------------------------------------------------------------------- 1 | // Load all the channels within this directory and all subdirectories. 2 | // Channel files must be named *_channel.js. 3 | 4 | const channels = require.context('.', true, /_channel\.js$/) 5 | channels.keys().forEach(channels) 6 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/javascript/controllers/application.js: -------------------------------------------------------------------------------- 1 | import { Application } from "@hotwired/stimulus" 2 | 3 | const application = Application.start() 4 | 5 | // Configure Stimulus development experience 6 | application.warnings = true 7 | application.debug = false 8 | window.Stimulus = application 9 | 10 | export { application } 11 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/javascript/controllers/hello_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from "@hotwired/stimulus" 2 | 3 | export default class extends Controller { 4 | connect() { 5 | this.element.textContent = "Hello World!" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/javascript/controllers/index.js: -------------------------------------------------------------------------------- 1 | // This file is auto-generated by ./bin/rails stimulus:manifest:update 2 | // Run that command whenever you add a new controller 3 | 4 | import { application } from "./application" 5 | 6 | import HelloController from "./hello_controller" 7 | application.register("hello", HelloController) 8 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/javascript/packs/application.js: -------------------------------------------------------------------------------- 1 | // This file is automatically compiled by Webpack, along with any other files 2 | // present in this directory. You're encouraged to place your actual application logic in 3 | // a relevant structure within app/javascript and only use these pack files to reference 4 | // that code so it'll be compiled. 5 | 6 | require("@rails/ujs").start() 7 | require("turbolinks").start() 8 | require("@rails/activestorage").start() 9 | require("channels") 10 | 11 | 12 | // Uncomment to copy all static images under ../images to the output folder and reference 13 | // them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>) 14 | // or the `imagePath` JavaScript helper below. 15 | // 16 | // const images = require.context('../images', true) 17 | // const imagePath = (name) => images(name, true) 18 | 19 | import 'vanilla-nested' 20 | 21 | document.addEventListener('vanilla-nested:fields-limit-reached', () => { 22 | document.getElementById('pets').insertAdjacentHTML('afterbegin', 'Limit reached') 23 | }) 24 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/javascript/packs/application_turbo.js: -------------------------------------------------------------------------------- 1 | // This file is automatically compiled by Webpack, along with any other files 2 | // present in this directory. You're encouraged to place your actual application logic in 3 | // a relevant structure within app/javascript and only use these pack files to reference 4 | // that code so it'll be compiled. 5 | 6 | require("@rails/ujs").start(); 7 | require("@rails/activestorage").start(); 8 | require("channels"); 9 | import "@hotwired/turbo-rails"; 10 | import "../controllers"; 11 | 12 | // Uncomment to copy all static images under ../images to the output folder and reference 13 | // them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>) 14 | // or the `imagePath` JavaScript helper below. 15 | // 16 | // const images = require.context('../images', true) 17 | // const imagePath = (name) => images(name, true) 18 | 19 | import "vanilla-nested"; 20 | 21 | document.addEventListener("vanilla-nested:fields-limit-reached", () => { 22 | document 23 | .getElementById("pets") 24 | .insertAdjacentHTML("afterbegin", "Limit reached"); 25 | }); 26 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | # Automatically retry jobs that encountered a deadlock 3 | # retry_on ActiveRecord::Deadlocked 4 | 5 | # Most jobs are safe to ignore if the underlying records are no longer available 6 | # discard_on ActiveJob::DeserializationError 7 | end 8 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | class ApplicationMailer < ActionMailer::Base 2 | default from: 'from@example.com' 3 | layout 'mailer' 4 | end 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | self.abstract_class = true 3 | end 4 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/app/models/concerns/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/models/pet.rb: -------------------------------------------------------------------------------- 1 | class Pet < ApplicationRecord 2 | belongs_to :user 3 | end -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/models/user.rb: -------------------------------------------------------------------------------- 1 | class User < ApplicationRecord 2 | has_many :pets 3 | accepts_nested_attributes_for :pets, limit: 3 4 | end 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | VanillaNestedTests 5 | <%= csrf_meta_tags %> 6 | <%= csp_meta_tag %> 7 | 8 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> 9 | <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> 10 | 11 | 12 | 13 | <%= yield %> 14 | 15 | 16 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/layouts/turbo.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | VanillaNestedTests 5 | <%= csrf_meta_tags %> 6 | <%= csp_meta_tag %> 7 | 8 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> 9 | <%= javascript_pack_tag 'application_turbo', 'data-turbolinks-track': 'reload' %> 10 | 11 | 12 | 13 | <%= yield %> 14 | 15 | 16 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/users/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for user do |form| %> 2 | <%= form.label :name %> 3 | <%= form.text_field :name %> 4 | 5 | <%= link_to_add_nested(form, :pets, '#pets') do %> 6 | Add Pet 7 | <% end %> 8 |

Pets

9 |
10 |

The limit is 3, configured in the model:

11 | <%= form.fields_for :pets do |pet_f| %> 12 | <%= render 'pet_fields', form: pet_f %> 13 | <% end %> 14 |
15 | <% end %> -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/users/_form_with_attributes_on_link_tag.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for user do |form| %> 2 | <%= form.label :name %> 3 | <%= form.text_field :name, tabindex: 1 %> 4 | 5 | <%= link_to_add_nested(form, :pets, '#pets', link_text: '+', tag_attributes: {title: "Add Pet", data: {some_data: 'is preserved'}}, partial: 'pet_fields_with_attributes_on_link_tag') %> 6 | 7 |

Pets

8 |
9 | <%= form.fields_for :pets do |pet_f| %> 10 | <%= render 'pet_fields_with_attributes_on_link_tag', form: pet_f %> 11 | <% end %> 12 |
13 | <% end %> -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/users/_form_with_custom_link_tag.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for user do |form| %> 2 | <%= form.label :name %> 3 | <%= form.text_field :name %> 4 | 5 | <%= link_to_add_nested(form, :pets, '#pets', tag: 'span', partial: 'pet_fields_with_custom_link_tag') do %> 6 | Add Pet 7 | <% end %> 8 |

Pets

9 |
10 | <%= form.fields_for :pets do |pet_f| %> 11 | <%= render 'pet_fields_with_custom_link_tag', form: pet_f %> 12 | <% end %> 13 |
14 | <% end %> -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/users/_form_with_undo.html.erb: -------------------------------------------------------------------------------- 1 | <%= form_for user do |form| %> 2 | <%= form.label :name %> 3 | <%= form.text_field :name %> 4 | 5 | <%= link_to_add_nested(form, :pets, '#pets', partial: 'pet_fields_with_undo') do %> 6 | Add Pet 7 | <% end %> 8 |

Pets

9 |
10 | <%= form.fields_for :pets do |pet_f| %> 11 | <%= render 'pet_fields_with_undo', form: pet_f %> 12 | <% end %> 13 |
14 | <% end %> -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/users/_pet_fields.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= form.label :name %> 3 | <%= form.text_field :name %> 4 | <%= form.label :color %> 5 | <%= form.text_field :color %> 6 | <%= link_to_remove_nested(form) do %> 7 | 8 | X 9 | 10 | <% end %> 11 |
-------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/users/_pet_fields_with_attributes_on_link_tag.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= form.label :name %> 3 | <%= form.text_field :name, tabindex: 2 %> 4 | <%= form.label :color %> 5 | <%= form.text_field :color, tabindex: 2 %> 6 | <%= link_to_remove_nested(form, tag: 'button', link_text: 'X', tag_attributes: {tabindex: "10"}) %> 7 |
-------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/users/_pet_fields_with_custom_link_tag.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= form.label :name %> 3 | <%= form.text_field :name %> 4 | <%= form.label :color %> 5 | <%= form.text_field :color %> 6 | <%= link_to_remove_nested(form, tag: 'div') do %> 7 | 8 | X 9 | 10 | <% end %> 11 |
-------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/users/_pet_fields_with_undo.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= form.label :name %> 3 | <%= form.text_field :name, style: "color: blue; display: inline-block" %> 4 | <%= form.label :color %> 5 | <%= form.text_field :color %> 6 | <%= link_to_remove_nested(form, undo_link_timeout: 400) do %> 7 | 8 | X 9 | 10 | <% end %> 11 |
-------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/users/index.html.erb: -------------------------------------------------------------------------------- 1 | <%= link_to 'New User', new_user_path %> 2 |
3 | <%= link_to 'New User with custom tags', new_with_custom_link_tag_users_path %> 4 |
5 | <%= link_to 'New User with undo', new_with_undo_users_path %> 6 |
7 | <%= link_to 'New User with attributes on links', new_with_attributes_on_link_tag_users_path %> -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/users/new.html.erb: -------------------------------------------------------------------------------- 1 | <%= render partial: 'form', locals: {user: @user} %> 2 | <%= link_to 'Back', users_path %> -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/users/new_with_attributes_on_link_tag.html.erb: -------------------------------------------------------------------------------- 1 | <%= render partial: 'form_with_attributes_on_link_tag', locals: {user: @user} %> 2 | <%= link_to 'Back', users_path %> -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/users/new_with_custom_link_tag.html.erb: -------------------------------------------------------------------------------- 1 | <%= render partial: 'form_with_custom_link_tag', locals: {user: @user} %> 2 | <%= link_to 'Back', users_path %> -------------------------------------------------------------------------------- /test/VanillaNestedTests/app/views/users/new_with_undo.html.erb: -------------------------------------------------------------------------------- 1 | <%= render partial: 'form_with_undo', locals: {user: @user} %> 2 | <%= link_to 'Back', users_path %> -------------------------------------------------------------------------------- /test/VanillaNestedTests/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | var validEnv = ['development', 'test', 'production'] 3 | var currentEnv = api.env() 4 | var isDevelopmentEnv = api.env('development') 5 | var isProductionEnv = api.env('production') 6 | var isTestEnv = api.env('test') 7 | 8 | if (!validEnv.includes(currentEnv)) { 9 | throw new Error( 10 | 'Please specify a valid `NODE_ENV` or ' + 11 | '`BABEL_ENV` environment variables. Valid values are "development", ' + 12 | '"test", and "production". Instead, received: ' + 13 | JSON.stringify(currentEnv) + 14 | '.' 15 | ) 16 | } 17 | 18 | return { 19 | presets: [ 20 | isTestEnv && [ 21 | '@babel/preset-env', 22 | { 23 | targets: { 24 | node: 'current' 25 | } 26 | } 27 | ], 28 | (isProductionEnv || isDevelopmentEnv) && [ 29 | '@babel/preset-env', 30 | { 31 | forceAllTransforms: true, 32 | useBuiltIns: 'entry', 33 | corejs: 3, 34 | modules: false, 35 | exclude: ['transform-typeof-symbol'] 36 | } 37 | ] 38 | ].filter(Boolean), 39 | plugins: [ 40 | 'babel-plugin-macros', 41 | '@babel/plugin-syntax-dynamic-import', 42 | isTestEnv && 'babel-plugin-dynamic-import-node', 43 | '@babel/plugin-transform-destructuring', 44 | [ 45 | '@babel/plugin-proposal-class-properties', 46 | { 47 | loose: true 48 | } 49 | ], 50 | [ 51 | '@babel/plugin-proposal-object-rest-spread', 52 | { 53 | useBuiltIns: true 54 | } 55 | ], 56 | [ 57 | '@babel/plugin-transform-runtime', 58 | { 59 | helpers: false, 60 | regenerator: true, 61 | corejs: false 62 | } 63 | ], 64 | [ 65 | '@babel/plugin-transform-regenerator', 66 | { 67 | async: false 68 | } 69 | ] 70 | ].filter(Boolean) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'bundle' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "rubygems" 12 | 13 | m = Module.new do 14 | module_function 15 | 16 | def invoked_as_script? 17 | File.expand_path($0) == File.expand_path(__FILE__) 18 | end 19 | 20 | def env_var_version 21 | ENV["BUNDLER_VERSION"] 22 | end 23 | 24 | def cli_arg_version 25 | return unless invoked_as_script? # don't want to hijack other binstubs 26 | return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` 27 | bundler_version = nil 28 | update_index = nil 29 | ARGV.each_with_index do |a, i| 30 | if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN 31 | bundler_version = a 32 | end 33 | next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ 34 | bundler_version = $1 35 | update_index = i 36 | end 37 | bundler_version 38 | end 39 | 40 | def gemfile 41 | gemfile = ENV["BUNDLE_GEMFILE"] 42 | return gemfile if gemfile && !gemfile.empty? 43 | 44 | File.expand_path("../../Gemfile", __FILE__) 45 | end 46 | 47 | def lockfile 48 | lockfile = 49 | case File.basename(gemfile) 50 | when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) 51 | else "#{gemfile}.lock" 52 | end 53 | File.expand_path(lockfile) 54 | end 55 | 56 | def lockfile_version 57 | return unless File.file?(lockfile) 58 | lockfile_contents = File.read(lockfile) 59 | return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ 60 | Regexp.last_match(1) 61 | end 62 | 63 | def bundler_version 64 | @bundler_version ||= 65 | env_var_version || cli_arg_version || 66 | lockfile_version 67 | end 68 | 69 | def bundler_requirement 70 | return "#{Gem::Requirement.default}.a" unless bundler_version 71 | 72 | bundler_gem_version = Gem::Version.new(bundler_version) 73 | 74 | requirement = bundler_gem_version.approximate_recommendation 75 | 76 | return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0") 77 | 78 | requirement += ".a" if bundler_gem_version.prerelease? 79 | 80 | requirement 81 | end 82 | 83 | def load_bundler! 84 | ENV["BUNDLE_GEMFILE"] ||= gemfile 85 | 86 | activate_bundler 87 | end 88 | 89 | def activate_bundler 90 | gem_error = activation_error_handling do 91 | gem "bundler", bundler_requirement 92 | end 93 | return if gem_error.nil? 94 | require_error = activation_error_handling do 95 | require "bundler/version" 96 | end 97 | return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) 98 | warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`" 99 | exit 42 100 | end 101 | 102 | def activation_error_handling 103 | yield 104 | nil 105 | rescue StandardError, LoadError => e 106 | e 107 | end 108 | end 109 | 110 | m.load_bundler! 111 | 112 | if m.invoked_as_script? 113 | load Gem.bin_path("bundler", "bundle") 114 | end 115 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path('../spring', __FILE__) 4 | rescue LoadError => e 5 | raise unless e.message.include?('spring') 6 | end 7 | APP_PATH = File.expand_path('../config/application', __dir__) 8 | require_relative '../config/boot' 9 | require 'rails/commands' 10 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path('../spring', __FILE__) 4 | rescue LoadError => e 5 | raise unless e.message.include?('spring') 6 | end 7 | require_relative '../config/boot' 8 | require 'rake' 9 | Rake.application.run 10 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'fileutils' 3 | 4 | # path to your application root. 5 | APP_ROOT = File.expand_path('..', __dir__) 6 | 7 | def system!(*args) 8 | system(*args) || abort("\n== Command #{args} failed ==") 9 | end 10 | 11 | FileUtils.chdir APP_ROOT do 12 | # This script is a way to setup or update your development environment automatically. 13 | # This script is idempotent, so that you can run it at anytime and get an expectable outcome. 14 | # Add necessary setup steps to this file. 15 | 16 | puts '== Installing dependencies ==' 17 | system! 'gem install bundler --conservative' 18 | system('bundle check') || system!('bundle install') 19 | 20 | # Install JavaScript dependencies 21 | system('bin/yarn') 22 | 23 | # puts "\n== Copying sample files ==" 24 | # unless File.exist?('config/database.yml') 25 | # FileUtils.cp 'config/database.yml.sample', 'config/database.yml' 26 | # end 27 | 28 | puts "\n== Preparing database ==" 29 | system! 'bin/rails db:prepare' 30 | 31 | puts "\n== Removing old logs and tempfiles ==" 32 | system! 'bin/rails log:clear tmp:clear' 33 | 34 | puts "\n== Restarting application server ==" 35 | system! 'bin/rails restart' 36 | end 37 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # This file loads Spring without using Bundler, in order to be fast. 4 | # It gets overwritten when you run the `spring binstub` command. 5 | 6 | unless defined?(Spring) 7 | require 'rubygems' 8 | require 'bundler' 9 | 10 | lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read) 11 | spring = lockfile.specs.detect { |spec| spec.name == 'spring' } 12 | if spring 13 | Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path 14 | gem 'spring', spring.version 15 | require 'spring/binstub' 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/bin/update-gem: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | yarn upgrade vanilla-nested 4 | rails webpacker:clobber -------------------------------------------------------------------------------- /test/VanillaNestedTests/bin/webpack: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "bundler/setup" 11 | 12 | require "webpacker" 13 | require "webpacker/webpack_runner" 14 | 15 | APP_ROOT = File.expand_path("..", __dir__) 16 | Dir.chdir(APP_ROOT) do 17 | Webpacker::WebpackRunner.run(ARGV) 18 | end 19 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/bin/webpack-dev-server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "bundler/setup" 11 | 12 | require "webpacker" 13 | require "webpacker/dev_server_runner" 14 | 15 | APP_ROOT = File.expand_path("..", __dir__) 16 | Dir.chdir(APP_ROOT) do 17 | Webpacker::DevServerRunner.run(ARGV) 18 | end 19 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/bin/yarn: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_ROOT = File.expand_path('..', __dir__) 3 | Dir.chdir(APP_ROOT) do 4 | begin 5 | exec "yarnpkg", *ARGV 6 | rescue Errno::ENOENT 7 | $stderr.puts "Yarn executable was not detected in the system." 8 | $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" 9 | exit 1 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative 'config/environment' 4 | 5 | run Rails.application 6 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/application.rb: -------------------------------------------------------------------------------- 1 | require_relative 'boot' 2 | 3 | require 'rails/all' 4 | 5 | # Require the gems listed in Gemfile, including any gems 6 | # you've limited to :test, :development, or :production. 7 | Bundler.require(*Rails.groups) 8 | 9 | module VanillaNestedTests 10 | class Application < Rails::Application 11 | # Initialize configuration defaults for originally generated Rails version. 12 | config.load_defaults 6.0 13 | 14 | # Settings in config/environments/* take precedence over those specified here. 15 | # Application configuration can go into files in config/initializers 16 | # -- all .rb files in that directory are automatically loaded after loading 17 | # the framework and any gems in your application. 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | require 'bootsnap/setup' # Speed up boot time by caching expensive operations. 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: redis 3 | url: redis://localhost:6379/1 4 | 5 | test: 6 | adapter: test 7 | 8 | production: 9 | adapter: redis 10 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 11 | channel_prefix: VanillaNestedTests_production 12 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/credentials.yml.enc: -------------------------------------------------------------------------------- 1 | Q6wp/lEZ/kd5tsSZJ0NJ22LvBU2lMoxAGzSD8/dTMn+Sxmme443dvzDsQaRRJdftkMpL90169Q0ly5Y2YVqsVx9wAJkr9CucJO7w/K4qd8zcxkVnmKZiUn9d6uiLrmQ26QXlqS5hv/l0ISmcjJlkPhg12pkm9K4J3KKRQlNlV+gA94r+FFiJjrSJgdSx4s/4MU8hK0qeGQDfWMYznwer4LnrD4IMXmMz18o3aigD+yYJ3rxeYYgMeXRbUYckVEjVhG9iRkb6BawG09QM6Pm6tA6PuXcXDRY+aLSH4J443C7tR3WYvJFTE8iJDE0d81hfbeQQ+8TZExhd6SErDjGVXfPhgU1fAV/CQIvyAV53DYVbYxixdHvCx0ap0Tj/6n9IZUbdk+7hJ4Y1b9hgRAbREWGS773OPSG0dl+r--K6kBu4IH5LW8ov/V--irsbtok3j/7+q+Sg942aeQ== -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite. Versions 3.8.0 and up are supported. 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem 'sqlite3' 6 | # 7 | default: &default 8 | adapter: sqlite3 9 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 10 | timeout: 5000 11 | 12 | development: 13 | <<: *default 14 | database: db/development.sqlite3 15 | 16 | # Warning: The database defined as "test" will be erased and 17 | # re-generated from your development database when you run "rake". 18 | # Do not set this db to the same as development or production. 19 | test: 20 | <<: *default 21 | database: db/test.sqlite3 22 | 23 | production: 24 | <<: *default 25 | database: db/production.sqlite3 26 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative 'application' 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/environments/development.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # In the development environment your application's code is reloaded on 5 | # every request. This slows down response time but is perfect for development 6 | # since you don't have to restart the web server when you make code changes. 7 | config.cache_classes = false 8 | 9 | # Do not eager load code on boot. 10 | config.eager_load = false 11 | 12 | # Show full error reports. 13 | config.consider_all_requests_local = true 14 | 15 | # Enable/disable caching. By default caching is disabled. 16 | # Run rails dev:cache to toggle caching. 17 | if Rails.root.join('tmp', 'caching-dev.txt').exist? 18 | config.action_controller.perform_caching = true 19 | config.action_controller.enable_fragment_cache_logging = true 20 | 21 | config.cache_store = :memory_store 22 | config.public_file_server.headers = { 23 | 'Cache-Control' => "public, max-age=#{2.days.to_i}" 24 | } 25 | else 26 | config.action_controller.perform_caching = false 27 | 28 | config.cache_store = :null_store 29 | end 30 | 31 | # Store uploaded files on the local file system (see config/storage.yml for options). 32 | config.active_storage.service = :local 33 | 34 | # Don't care if the mailer can't send. 35 | config.action_mailer.raise_delivery_errors = false 36 | 37 | config.action_mailer.perform_caching = false 38 | 39 | # Print deprecation notices to the Rails logger. 40 | config.active_support.deprecation = :log 41 | 42 | # Raise an error on page load if there are pending migrations. 43 | config.active_record.migration_error = :page_load 44 | 45 | # Highlight code that triggered database queries in logs. 46 | config.active_record.verbose_query_logs = true 47 | 48 | # Debug mode disables concatenation and preprocessing of assets. 49 | # This option may cause significant delays in view rendering with a large 50 | # number of complex assets. 51 | config.assets.debug = true 52 | 53 | # Suppress logger output for asset requests. 54 | config.assets.quiet = true 55 | 56 | # Raises error for missing translations. 57 | # config.action_view.raise_on_missing_translations = true 58 | 59 | # Use an evented file watcher to asynchronously detect changes in source code, 60 | # routes, locales, etc. This feature depends on the listen gem. 61 | config.file_watcher = ActiveSupport::EventedFileUpdateChecker 62 | end 63 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/environments/production.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # Code is not reloaded between requests. 5 | config.cache_classes = true 6 | 7 | # Eager load code on boot. This eager loads most of Rails and 8 | # your application in memory, allowing both threaded web servers 9 | # and those relying on copy on write to perform better. 10 | # Rake tasks automatically ignore this option for performance. 11 | config.eager_load = true 12 | 13 | # Full error reports are disabled and caching is turned on. 14 | config.consider_all_requests_local = false 15 | config.action_controller.perform_caching = true 16 | 17 | # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] 18 | # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). 19 | # config.require_master_key = true 20 | 21 | # Disable serving static files from the `/public` folder by default since 22 | # Apache or NGINX already handles this. 23 | config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? 24 | 25 | # Compress CSS using a preprocessor. 26 | # config.assets.css_compressor = :sass 27 | 28 | # Do not fallback to assets pipeline if a precompiled asset is missed. 29 | config.assets.compile = false 30 | 31 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 32 | # config.action_controller.asset_host = 'http://assets.example.com' 33 | 34 | # Specifies the header that your server uses for sending files. 35 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache 36 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX 37 | 38 | # Store uploaded files on the local file system (see config/storage.yml for options). 39 | config.active_storage.service = :local 40 | 41 | # Mount Action Cable outside main process or domain. 42 | # config.action_cable.mount_path = nil 43 | # config.action_cable.url = 'wss://example.com/cable' 44 | # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] 45 | 46 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 47 | # config.force_ssl = true 48 | 49 | # Use the lowest log level to ensure availability of diagnostic information 50 | # when problems arise. 51 | config.log_level = :debug 52 | 53 | # Prepend all log lines with the following tags. 54 | config.log_tags = [ :request_id ] 55 | 56 | # Use a different cache store in production. 57 | # config.cache_store = :mem_cache_store 58 | 59 | # Use a real queuing backend for Active Job (and separate queues per environment). 60 | # config.active_job.queue_adapter = :resque 61 | # config.active_job.queue_name_prefix = "VanillaNestedTests_production" 62 | 63 | config.action_mailer.perform_caching = false 64 | 65 | # Ignore bad email addresses and do not raise email delivery errors. 66 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 67 | # config.action_mailer.raise_delivery_errors = false 68 | 69 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 70 | # the I18n.default_locale when a translation cannot be found). 71 | config.i18n.fallbacks = true 72 | 73 | # Send deprecation notices to registered listeners. 74 | config.active_support.deprecation = :notify 75 | 76 | # Use default logging formatter so that PID and timestamp are not suppressed. 77 | config.log_formatter = ::Logger::Formatter.new 78 | 79 | # Use a different logger for distributed setups. 80 | # require 'syslog/logger' 81 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') 82 | 83 | if ENV["RAILS_LOG_TO_STDOUT"].present? 84 | logger = ActiveSupport::Logger.new(STDOUT) 85 | logger.formatter = config.log_formatter 86 | config.logger = ActiveSupport::TaggedLogging.new(logger) 87 | end 88 | 89 | # Do not dump schema after migrations. 90 | config.active_record.dump_schema_after_migration = false 91 | 92 | # Inserts middleware to perform automatic connection switching. 93 | # The `database_selector` hash is used to pass options to the DatabaseSelector 94 | # middleware. The `delay` is used to determine how long to wait after a write 95 | # to send a subsequent read to the primary. 96 | # 97 | # The `database_resolver` class is used by the middleware to determine which 98 | # database is appropriate to use based on the time delay. 99 | # 100 | # The `database_resolver_context` class is used by the middleware to set 101 | # timestamps for the last write to the primary. The resolver uses the context 102 | # class timestamps to determine how long to wait before reading from the 103 | # replica. 104 | # 105 | # By default Rails will store a last write timestamp in the session. The 106 | # DatabaseSelector middleware is designed as such you can define your own 107 | # strategy for connection switching and pass that into the middleware through 108 | # these configuration options. 109 | # config.active_record.database_selector = { delay: 2.seconds } 110 | # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver 111 | # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session 112 | end 113 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/environments/test.rb: -------------------------------------------------------------------------------- 1 | # The test environment is used exclusively to run your application's 2 | # test suite. You never need to work with it otherwise. Remember that 3 | # your test database is "scratch space" for the test suite and is wiped 4 | # and recreated between test runs. Don't rely on the data there! 5 | 6 | Rails.application.configure do 7 | # Settings specified here will take precedence over those in config/application.rb. 8 | 9 | config.cache_classes = false 10 | 11 | # Do not eager load code on boot. This avoids loading your whole application 12 | # just for the purpose of running a single test. If you are using a tool that 13 | # preloads Rails for running tests, you may have to set it to true. 14 | config.eager_load = false 15 | 16 | # Configure public file server for tests with Cache-Control for performance. 17 | config.public_file_server.enabled = true 18 | config.public_file_server.headers = { 19 | 'Cache-Control' => "public, max-age=#{1.hour.to_i}" 20 | } 21 | 22 | # Show full error reports and disable caching. 23 | config.consider_all_requests_local = true 24 | config.action_controller.perform_caching = false 25 | config.cache_store = :null_store 26 | 27 | # Raise exceptions instead of rendering exception templates. 28 | config.action_dispatch.show_exceptions = false 29 | 30 | # Disable request forgery protection in test environment. 31 | config.action_controller.allow_forgery_protection = false 32 | 33 | # Store uploaded files on the local file system in a temporary directory. 34 | config.active_storage.service = :test 35 | 36 | config.action_mailer.perform_caching = false 37 | 38 | # Tell Action Mailer not to deliver emails to the real world. 39 | # The :test delivery method accumulates sent emails in the 40 | # ActionMailer::Base.deliveries array. 41 | config.action_mailer.delivery_method = :test 42 | 43 | # Print deprecation notices to the stderr. 44 | config.active_support.deprecation = :stderr 45 | 46 | # Raises error for missing translations. 47 | # config.action_view.raise_on_missing_translations = true 48 | end 49 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # ActiveSupport::Reloader.to_prepare do 4 | # ApplicationController.renderer.defaults.merge!( 5 | # http_host: 'example.org', 6 | # https: false 7 | # ) 8 | # end 9 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Add additional assets to the asset load path. 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | # Add Yarn node_modules folder to the asset load path. 9 | Rails.application.config.assets.paths << Rails.root.join('node_modules') 10 | 11 | # Precompile additional assets. 12 | # application.js, application.css, and all non-JS/CSS in the app/assets 13 | # folder are already added. 14 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 15 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/initializers/content_security_policy.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Define an application-wide content security policy 4 | # For further information see the following documentation 5 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy 6 | 7 | # Rails.application.config.content_security_policy do |policy| 8 | # policy.default_src :self, :https 9 | # policy.font_src :self, :https, :data 10 | # policy.img_src :self, :https, :data 11 | # policy.object_src :none 12 | # policy.script_src :self, :https 13 | # policy.style_src :self, :https 14 | # # If you are using webpack-dev-server then specify webpack-dev-server host 15 | # policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development? 16 | 17 | # # Specify URI for violation reports 18 | # # policy.report_uri "/csp-violation-report-endpoint" 19 | # end 20 | 21 | # If you are using UJS then enable automatic nonce generation 22 | # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } 23 | 24 | # Set the nonce only to specific directives 25 | # Rails.application.config.content_security_policy_nonce_directives = %w(script-src) 26 | 27 | # Report CSP violations to a specified URI 28 | # For further information see the following documentation: 29 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only 30 | # Rails.application.config.content_security_policy_report_only = true 31 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Specify a serializer for the signed and encrypted cookie jars. 4 | # Valid options are :json, :marshal, and :hybrid. 5 | Rails.application.config.action_dispatch.cookies_serializer = :json 6 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # The following keys must be escaped otherwise they will not be retrieved by 20 | # the default I18n backend: 21 | # 22 | # true, false, on, off, yes, no 23 | # 24 | # Instead, surround them with single quotes. 25 | # 26 | # en: 27 | # 'true': 'foo' 28 | # 29 | # To learn more, please read the Rails Internationalization guide 30 | # available at https://guides.rubyonrails.org/i18n.html. 31 | 32 | en: 33 | hello: "Hello world" 34 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/puma.rb: -------------------------------------------------------------------------------- 1 | # Puma can serve each request in a thread from an internal thread pool. 2 | # The `threads` method setting takes two numbers: a minimum and maximum. 3 | # Any libraries that use thread pools should be configured to match 4 | # the maximum value specified for Puma. Default is set to 5 threads for minimum 5 | # and maximum; this matches the default thread size of Active Record. 6 | # 7 | max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } 8 | min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } 9 | threads min_threads_count, max_threads_count 10 | 11 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000. 12 | # 13 | port ENV.fetch("PORT") { 3000 } 14 | 15 | # Specifies the `environment` that Puma will run in. 16 | # 17 | environment ENV.fetch("RAILS_ENV") { "development" } 18 | 19 | # Specifies the `pidfile` that Puma will use. 20 | pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } 21 | 22 | # Specifies the number of `workers` to boot in clustered mode. 23 | # Workers are forked web server processes. If using threads and workers together 24 | # the concurrency of the application would be max `threads` * `workers`. 25 | # Workers do not work on JRuby or Windows (both of which do not support 26 | # processes). 27 | # 28 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 } 29 | 30 | # Use the `preload_app!` method when specifying a `workers` number. 31 | # This directive tells Puma to first boot the application and load code 32 | # before forking the application. This takes advantage of Copy On Write 33 | # process behavior so workers use less memory. 34 | # 35 | # preload_app! 36 | 37 | # Allow puma to be restarted by `rails restart` command. 38 | plugin :tmp_restart 39 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html 3 | resources :users do 4 | collection do 5 | get :new_with_custom_link_tag 6 | get :new_with_undo 7 | get :new_with_attributes_on_link_tag 8 | get :new_using_turbo 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/spring.rb: -------------------------------------------------------------------------------- 1 | Spring.watch( 2 | ".ruby-version", 3 | ".rbenv-vars", 4 | "tmp/restart.txt", 5 | "tmp/caching-dev.txt" 6 | ) 7 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join("tmp/storage") %> 4 | 5 | local: 6 | service: Disk 7 | root: <%= Rails.root.join("storage") %> 8 | 9 | # Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) 10 | # amazon: 11 | # service: S3 12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> 13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> 14 | # region: us-east-1 15 | # bucket: your_own_bucket 16 | 17 | # Remember not to checkin your GCS keyfile to a repository 18 | # google: 19 | # service: GCS 20 | # project: your_project 21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> 22 | # bucket: your_own_bucket 23 | 24 | # Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) 25 | # microsoft: 26 | # service: AzureStorage 27 | # storage_account_name: your_account_name 28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> 29 | # container: your_container_name 30 | 31 | # mirror: 32 | # service: Mirror 33 | # primary: local 34 | # mirrors: [ amazon, google, microsoft ] 35 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/webpack/development.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development' 2 | 3 | const environment = require('./environment') 4 | 5 | module.exports = environment.toWebpackConfig() 6 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/webpack/environment.js: -------------------------------------------------------------------------------- 1 | const { environment } = require('@rails/webpacker') 2 | 3 | module.exports = environment 4 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/webpack/production.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'production' 2 | 3 | const environment = require('./environment') 4 | 5 | module.exports = environment.toWebpackConfig() 6 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/webpack/test.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development' 2 | 3 | const environment = require('./environment') 4 | 5 | module.exports = environment.toWebpackConfig() 6 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/config/webpacker.yml: -------------------------------------------------------------------------------- 1 | # Note: You must restart bin/webpack-dev-server for changes to take effect 2 | 3 | default: &default 4 | source_path: app/javascript 5 | source_entry_path: packs 6 | public_root_path: public 7 | public_output_path: packs 8 | cache_path: tmp/cache/webpacker 9 | check_yarn_integrity: false 10 | webpack_compile_output: true 11 | 12 | # Additional paths webpack should lookup modules 13 | # ['app/assets', 'engine/foo/app/assets'] 14 | resolved_paths: [] 15 | 16 | # Reload manifest.json on all requests so we reload latest compiled packs 17 | cache_manifest: false 18 | 19 | # Extract and emit a css file 20 | extract_css: false 21 | 22 | static_assets_extensions: 23 | - .jpg 24 | - .jpeg 25 | - .png 26 | - .gif 27 | - .tiff 28 | - .ico 29 | - .svg 30 | - .eot 31 | - .otf 32 | - .ttf 33 | - .woff 34 | - .woff2 35 | 36 | extensions: 37 | - .mjs 38 | - .js 39 | - .sass 40 | - .scss 41 | - .css 42 | - .module.sass 43 | - .module.scss 44 | - .module.css 45 | - .png 46 | - .svg 47 | - .gif 48 | - .jpeg 49 | - .jpg 50 | 51 | development: 52 | <<: *default 53 | compile: true 54 | 55 | # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules 56 | check_yarn_integrity: true 57 | 58 | # Reference: https://webpack.js.org/configuration/dev-server/ 59 | dev_server: 60 | https: false 61 | host: localhost 62 | port: 3035 63 | public: localhost:3035 64 | hmr: false 65 | # Inline should be set to true if using HMR 66 | inline: true 67 | overlay: true 68 | compress: true 69 | disable_host_check: true 70 | use_local_ip: false 71 | quiet: false 72 | pretty: false 73 | headers: 74 | 'Access-Control-Allow-Origin': '*' 75 | watch_options: 76 | ignored: '**/node_modules/**' 77 | 78 | 79 | test: 80 | <<: *default 81 | compile: true 82 | 83 | # Compile test packs to a separate directory 84 | public_output_path: packs-test 85 | 86 | production: 87 | <<: *default 88 | 89 | # Production depends on precompilation of packs prior to booting for performance. 90 | compile: false 91 | 92 | # Extract and emit a css file 93 | extract_css: true 94 | 95 | # Cache manifest.json for performance 96 | cache_manifest: true 97 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/db/migrate/20210220015506_create_users.rb: -------------------------------------------------------------------------------- 1 | class CreateUsers < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :users do |t| 4 | t.string :name 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/db/migrate/20210220015510_create_pets.rb: -------------------------------------------------------------------------------- 1 | class CreatePets < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :pets do |t| 4 | t.references :user 5 | t.string :name 6 | t.string :color 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/db/schema.rb: -------------------------------------------------------------------------------- 1 | # This file is auto-generated from the current state of the database. Instead 2 | # of editing this file, please use the migrations feature of Active Record to 3 | # incrementally modify your database, and then regenerate this schema definition. 4 | # 5 | # This file is the source Rails uses to define your schema when running `bin/rails 6 | # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to 7 | # be faster and is potentially less error prone than running all of your 8 | # migrations from scratch. Old migrations may fail to apply correctly if those 9 | # migrations use external dependencies or application code. 10 | # 11 | # It's strongly recommended that you check this file into your version control system. 12 | 13 | ActiveRecord::Schema.define(version: 2021_02_20_015510) do 14 | 15 | create_table "pets", force: :cascade do |t| 16 | t.bigint "user_id" 17 | t.string "name" 18 | t.string "color" 19 | t.index ["user_id"], name: "index_pets_on_user_id" 20 | end 21 | 22 | create_table "users", force: :cascade do |t| 23 | t.string "name" 24 | end 25 | 26 | end 27 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). 3 | # 4 | # Examples: 5 | # 6 | # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) 7 | # Character.create(name: 'Luke', movie: movies.first) 8 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/lib/assets/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/lib/tasks/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/log/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "VanillaNestedTests", 3 | "private": true, 4 | "dependencies": { 5 | "@hotwired/stimulus": "^3.0.1", 6 | "@hotwired/turbo-rails": "^7.0.1", 7 | "@rails/actioncable": "^6.0.0", 8 | "@rails/activestorage": "^6.0.0", 9 | "@rails/ujs": "^6.0.0", 10 | "@rails/webpacker": "4.3.0", 11 | "turbolinks": "^5.2.0", 12 | "vanilla-nested": "file:../.." 13 | }, 14 | "version": "0.1.0", 15 | "devDependencies": { 16 | "webpack-dev-server": "^3.11.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('postcss-import'), 4 | require('postcss-flexbugs-fixes'), 5 | require('postcss-preset-env')({ 6 | autoprefixer: { 7 | flexbox: 'no-2009' 8 | }, 9 | stage: 3 10 | }) 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/public/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /test/VanillaNestedTests/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/public/apple-touch-icon.png -------------------------------------------------------------------------------- /test/VanillaNestedTests/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/public/favicon.ico -------------------------------------------------------------------------------- /test/VanillaNestedTests/public/robots.txt: -------------------------------------------------------------------------------- 1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/storage/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/storage/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/test/application_system_test_case.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class ApplicationSystemTestCase < ActionDispatch::SystemTestCase 4 | driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400] 5 | end 6 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/test/channels/application_cable/connection_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase 4 | # test "connects with cookies" do 5 | # cookies.signed[:user_id] = 42 6 | # 7 | # connect 8 | # 9 | # assert_equal connection.user_id, "42" 10 | # end 11 | end 12 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/test/controllers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/test/controllers/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/test/fixtures/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/test/fixtures/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/test/fixtures/files/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/test/fixtures/files/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/test/helpers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/test/helpers/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/test/helpers/vanilla_nested_helpers_test.rb: -------------------------------------------------------------------------------- 1 | class VanillaNestedHelpersTest < ActionView::TestCase 2 | setup do 3 | controller.prepend_view_path(Rails.root.join('app/views/users')) 4 | @user = User.new 5 | end 6 | 7 | class Add < self 8 | setup do 9 | @method = ActionView::Base.instance_method(:link_to_add_nested).bind(self) 10 | end 11 | 12 | test('accepts custom link text and block') do 13 | form_for @user do |f| 14 | link_txt = @method.call(f, :pets, '#pets', link_text: 'my custom text') 15 | link = Nokogiri.HTML(link_txt) 16 | assert_equal 'my custom text', link.text 17 | assert_empty link.css('i.aaa') 18 | 19 | link_txt = @method.call(f, :pets, '#pets') do 20 | "".html_safe 21 | end 22 | 23 | link = Nokogiri.HTML(link_txt) 24 | assert_not_empty link.css('i.aaa') 25 | end 26 | end 27 | 28 | test('accepts custom classes') do 29 | form_for @user do |f| 30 | link_txt = @method.call(f, :pets, '#pets', link_classes: 'my-class') 31 | link = Nokogiri.HTML(link_txt) 32 | assert_not_empty link.css('.vanilla-nested-add.my-class') 33 | 34 | link_txt = @method.call(f, :pets, '#pets', link_classes: 'class1 class2') 35 | 36 | link = Nokogiri.HTML(link_txt) 37 | assert_not_empty link.css('.vanilla-nested-add.class1.class2') 38 | assert_empty link.css('.vanilla-nested-add.my-class') 39 | end 40 | end 41 | end 42 | 43 | class Remove < self 44 | setup do 45 | @method = ActionView::Base.instance_method(:link_to_remove_nested).bind(self) 46 | end 47 | 48 | test('accepts custom link text and block') do 49 | form_for @user do |f| 50 | link_txt = @method.call(f, link_text: 'my custom text') 51 | link = Nokogiri.HTML(link_txt) 52 | assert_equal 'my custom text', link.text 53 | assert_empty link.css('i.aaa') 54 | 55 | link_txt = @method.call(f) do 56 | "".html_safe 57 | end 58 | 59 | link = Nokogiri.HTML(link_txt) 60 | assert_not_empty link.css('i.aaa') 61 | end 62 | end 63 | 64 | test('accepts custom classes') do 65 | form_for @user do |f| 66 | link_txt = @method.call(f, link_classes: 'my-class') 67 | link = Nokogiri.HTML(link_txt) 68 | assert_not_empty link.css('.vanilla-nested-remove.my-class') 69 | 70 | link_txt = @method.call(f, link_classes: 'class1 class2') 71 | 72 | link = Nokogiri.HTML(link_txt) 73 | assert_not_empty link.css('.vanilla-nested-remove.class1.class2') 74 | assert_empty link.css('.vanilla-nested-remove.my-class') 75 | end 76 | end 77 | end 78 | end -------------------------------------------------------------------------------- /test/VanillaNestedTests/test/integration/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/test/integration/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/test/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/test/mailers/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/test/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/test/models/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/test/system/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/test/system/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/test/system/html_tag_test.rb: -------------------------------------------------------------------------------- 1 | require "application_system_test_case" 2 | 3 | class HtmlTagTest < ApplicationSystemTestCase 4 | test "accepts custom tags for link_to_add/remove_nested" do 5 | visit new_with_custom_link_tag_users_path 6 | 7 | assert_selector '#new_user' 8 | 9 | assert_selector '.pet-fields', count: 1 10 | 11 | within '.pet-fields:nth-of-type(1)' do 12 | fill_in 'Name', with: 'Spike' 13 | end 14 | 15 | # wrapper is a SPAN tag 16 | find('span.vanilla-nested-add', text: 'Add Pet').click 17 | 18 | assert_selector '.pet-fields', count: 2 19 | 20 | within '.pet-fields:nth-of-type(2)' do 21 | fill_in 'Name', with: 'Marnie' 22 | end 23 | 24 | # wrapper is a DIV tag 25 | within '.pet-fields:nth-of-type(1)' do 26 | find('div.vanilla-nested-remove', text: 'X').click 27 | end 28 | end 29 | 30 | test "accepts attributes for the custom tags for link_to_add/remove_nested" do 31 | visit new_with_attributes_on_link_tag_users_path 32 | 33 | # 'add' wrapper has a title attribute 34 | # it also preserves data and classes attributes 35 | # tag_attributes: {title: "Add Pet", data: {some_data: 'is preserved'} 36 | find('.vanilla-nested-add[title="Add Pet"][data-some-data="is preserved"]', text: '+').click 37 | 38 | # wrapper has a tabindex 39 | # tag: 'button', tag_attributes: {tabindex: "10"} 40 | within '.pet-fields:nth-of-type(1)' do 41 | find('button.vanilla-nested-remove[tabindex="10"]', text: 'X').click 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/test/system/undo_test.rb: -------------------------------------------------------------------------------- 1 | require "application_system_test_case" 2 | 3 | class UndoTest < ApplicationSystemTestCase 4 | test "can undo" do 5 | visit new_with_undo_users_path 6 | 7 | assert_selector '#new_user' 8 | 9 | assert_selector '.pet-fields', count: 1 10 | 11 | within '.pet-fields:nth-of-type(1)' do 12 | fill_in 'Name', with: 'Spike' 13 | end 14 | 15 | find('.vanilla-nested-add', text: 'Add Pet').click 16 | 17 | assert_selector '.pet-fields', count: 2 18 | 19 | # test with fields added dynamically 20 | within '.pet-fields:nth-of-type(2)' do 21 | assert_selector '.vanilla-nested-undo', text: 'Undo', count: 0 22 | find('.vanilla-nested-remove', text: 'X').click 23 | 24 | # added the Undo button 25 | assert_selector '.vanilla-nested-undo', text: 'Undo', count: 1 26 | 27 | # test `hidden` style handling 28 | assert_selector '[style="color: blue; display: none;"]', count: 1, visible: false 29 | assert_selector '[style="color: blue; display: inline-block;"]', count: 0, visible: false 30 | assert_selector '[style="display: none;"]', visible: false 31 | 32 | # click undo to stop the removal 33 | find('.vanilla-nested-undo', text: 'Undo').click() 34 | assert_selector '.vanilla-nested-undo', text: 'Undo', count: 0 35 | 36 | # test `after-undo` style handling 37 | assert_selector '[style="color: blue; display: none;"]', count: 0 38 | assert_selector '[style="color: blue; display: inline-block;"]', count: 1 39 | assert_selector '[style="display: none;"]', count: 0 40 | 41 | # click to remove for real 42 | find('.vanilla-nested-remove', text: 'X').click 43 | end 44 | 45 | sleep(0.5) # undo timeout is configured as 400ms 46 | 47 | assert_selector '.pet-fields', count: 1 48 | assert_selector '.pet-fields', visible: :hidden, count: 0 49 | 50 | # test with fields rendered server side 51 | within '.pet-fields:nth-of-type(1)' do 52 | assert_selector '.vanilla-nested-undo', text: 'Undo', count: 0 53 | find('.vanilla-nested-remove', text: 'X').click 54 | 55 | # added the Undo button 56 | assert_selector '.vanilla-nested-undo', text: 'Undo', count: 1 57 | 58 | # click undo to stop the removal 59 | find('.vanilla-nested-undo', text: 'Undo').click() 60 | assert_selector '.vanilla-nested-undo', text: 'Undo', count: 0 61 | 62 | # click to remove for real 63 | find('.vanilla-nested-remove', text: 'X').click 64 | end 65 | 66 | sleep(0.5) # undo timeout is configured as 400ms 67 | 68 | assert_selector '.pet-fields', count: 0 69 | assert_selector '.pet-fields', visible: :hidden, count: 1 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/test/system/vanilla_nested_test.rb: -------------------------------------------------------------------------------- 1 | require "application_system_test_case" 2 | 3 | class VanillaNestedTest < ApplicationSystemTestCase 4 | test "adds/removes fields" do 5 | visit users_path 6 | click_link 'New User' 7 | 8 | assert_selector '#new_user' 9 | 10 | # one field, not added by vanilla-nested 11 | assert_selector '.pet-fields:not(.added-by-vanilla-nested)', count: 1 12 | 13 | within '.pet-fields:nth-of-type(1)' do 14 | fill_in 'Name', with: 'Spike' 15 | end 16 | 17 | # adds 1 pet 18 | find('a.vanilla-nested-add', text: 'Add Pet').click 19 | 20 | assert_selector '.pet-fields', count: 2 21 | # one added and one not added by vanilla-nested 22 | assert_selector '.pet-fields:not(.added-by-vanilla-nested)', count: 1 23 | assert_selector '.pet-fields.added-by-vanilla-nested', count: 1 24 | 25 | within '.pet-fields:nth-of-type(2)' do 26 | fill_in 'Name', with: 'Marnie' 27 | end 28 | 29 | # removes first pet 30 | within '.pet-fields:nth-of-type(1)' do 31 | find('a.vanilla-nested-remove', text: 'X').click 32 | end 33 | 34 | # first pet is hidden 35 | assert_selector '.pet-fields', count: 1, visible: :hidden do |wrapper| 36 | assert_equal 1, wrapper.all('*', visible: :hidden).length 37 | destroy = wrapper.all('*', visible: :hidden).first 38 | assert_match /\[_destroy\]\z/, destroy.native.attribute('name') 39 | assert_equal '1', destroy.value 40 | end 41 | 42 | # second pet is visible 43 | assert_selector '.pet-fields', count: 1, visible: :visible do |wrapper| 44 | # verify it's the second one 45 | assert_equal 'Marnie', wrapper.first('input').value 46 | end 47 | 48 | within '.pet-fields:nth-of-type(2)' do 49 | find('a.vanilla-nested-remove', text: 'X').click 50 | end 51 | 52 | # second pet is not there anymore 53 | assert_selector '.pet-fields', count: 1, visible: :hidden 54 | end 55 | 56 | test "emits an event when the association limit is reached" do 57 | visit new_user_path 58 | 59 | assert_selector '#new_user' 60 | 61 | assert_selector '.pet-fields', count: 1 62 | 63 | find('a.vanilla-nested-add', text: 'Add Pet').click 64 | 65 | assert_selector '.pet-fields', count: 2 66 | 67 | assert_selector 'span', text: 'Limit reached', count: 0 68 | 69 | find('a.vanilla-nested-add', text: 'Add Pet').click 70 | 71 | assert_selector '.pet-fields', count: 3 72 | assert_selector 'span', text: 'Limit reached', count: 1 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/test/test_helper.rb: -------------------------------------------------------------------------------- 1 | ENV['RAILS_ENV'] ||= 'test' 2 | require_relative '../config/environment' 3 | require 'rails/test_help' 4 | 5 | class ActiveSupport::TestCase 6 | # Run tests in parallel with specified workers 7 | parallelize(workers: :number_of_processors) 8 | 9 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. 10 | fixtures :all 11 | 12 | # Add more helper methods to be used by all tests here... 13 | end 14 | -------------------------------------------------------------------------------- /test/VanillaNestedTests/tmp/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/tmp/.keep -------------------------------------------------------------------------------- /test/VanillaNestedTests/vendor/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arielj/vanilla-nested/cab8f390dc99eed933952f6fcc14603bad30c6a8/test/VanillaNestedTests/vendor/.keep -------------------------------------------------------------------------------- /vanilla_nested.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |s| 2 | s.name = 'vanilla_nested' 3 | s.version = '1.7.0' 4 | s.authors = ['Ariel Juodziukynas '] 5 | s.email = 'arieljuod@gmail.com' 6 | s.date = '2019-04-10' 7 | s.summary = 'Dynamic nested forms using vanilla javascript' 8 | s.files = [ 9 | 'app/assets/javascripts/vanilla_nested.js', 10 | 'lib/vanilla_nested/view_helpers.rb', 11 | 'lib/vanilla_nested.rb' 12 | ] 13 | s.license = 'MIT' 14 | s.homepage = 'https://github.com/arielj/vanilla-nested' 15 | s.require_paths = ['lib'] 16 | end 17 | --------------------------------------------------------------------------------