diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e0f66a4..8867b55 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,6 +9,19 @@ on: jobs: build: runs-on: ubuntu-latest + services: + postgres: + image: postgres:11-alpine + env: + POSTGRES_DB: rails_test + POSTGRES_USER: rails + POSTGRES_PASSWORD: password + ports: + - 5432:5432 + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + env: + RAILS_ENV: test + DATABASE_URL: "postgres://rails:password@localhost:5432/rails_test" name: Ruby ${{ matrix.ruby }} strategy: matrix: @@ -16,10 +29,18 @@ jobs: - "3.2.2" steps: - uses: actions/checkout@v3 + - name: Install prerequisites + run: | + sudo apt-get install -y libvips + sudo apt-get install -yqq libpq-dev - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} bundler-cache: true + - name: Set up database + run: | + bundle exec rake db:create + bundle exec rake db:migrate - name: Run test cases run: bundle exec rake diff --git a/.gitignore b/.gitignore index 014fe7a..041d5ba 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ demo/log/** demo/tmp/**/* demo/*.byebug_history demo/public/assets +demo/config/database.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index c8f9639..3e56d5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,114 @@ -## [Unreleased] +# Change Log + +You can find recent releases with docs in GitHub: + +https://github.com/shivam091/rails_bootstrap_form/releases + +## [0.6.1](https://github.com/shivam091/rails_bootstrap_form/compare/v0.6.0...v0.6.1) - 2023-05-24 + +### What's changed +- Changes in directory structure +- Added test cases +- Added README and CHANGELOG + +## [0.6.0](https://github.com/shivam091/rails_bootstrap_form/compare/v0.5.3...v0.6.0) - 2023-05-22 + +### What's new +- Added support for **`horizontal`** form layout + +## [0.5.3](https://github.com/shivam091/rails_bootstrap_form/compare/v0.5.2...v0.5.3) - 2023-05-21 + +### What's changed +- Added new option inline to render checkboxes and radio buttons inline + +## [0.5.2](https://github.com/shivam091/rails_bootstrap_form/compare/v0.5.1...v0.5.2) - 2023-05-21 + +### What's new +- Added option to add custom options to the field's wrapper +- Added option to apply user defined CSS class to the field +- Added option to control size of input group and field +- Added provision to change id of the field and corresponding label + +### What's changed +- Added `mb-3` css class to field wrapper if radio buttons or check boxes are not inline + +## [0.5.1](https://github.com/shivam091/rails_bootstrap_form/compare/v0.5.0...v0.5.1) - 2023-05-20 + +### What's new +- Wrapped `collection_check_boxes` and `collection_radio_buttons` inside field wrapper. + +## [0.5.0](https://github.com/shivam091/rails_bootstrap_form/compare/v0.4.2...v0.5.0) - 2023-05-20 + +### What's new +- Added wrapper methods for `check_box`, `collection_check_boxes`, `radio_button`, and `collection_radio_buttons` to support Bootstrap 5 form styles + +### What's changed +- Replaced HTML tag of help_text component from `` to `
` + +## [0.4.2](https://github.com/shivam091/rails_bootstrap_form/compare/v0.4.1...v0.4.2) - 2023-05-16 + +### What's new +- Added wrapper method for `grouped_collection_select` + +## [0.4.1](https://github.com/shivam091/rails_bootstrap_form/compare/v0.4.0...v0.4.1) - 2023-05-16 -## [0.1.0] - 2023-05-15 +### What's fixed +- Replaced `reverse_merge` by `deep_merge!` in adding new option values to fix bug causing not to merge options. + +## [0.4.0](https://github.com/shivam091/rails_bootstrap_form/compare/v0.3.1...v0.4.0) - 2023-05-15 + +### What's new +- Added wrapper methods for `range_field` and `color_field` +- Added wrapper methods for `time_zone_select` and `hidden_field` +- Added wrapper methods for `date_select`, `time_select`, and `datetime_select` +- Added wrapper method to render static control +- Added wrapper method for `collection_select` + +## [0.3.1](https://github.com/shivam091/rails_bootstrap_form/compare/v0.3.0...v0.3.1) - 2023-05-15 + +### What's fixed +- Bug causing fields to wrap in input group even when content to append and prepend is not available. + +## [0.3.0](https://github.com/shivam091/rails_bootstrap_form/compare/v0.2.3...v0.3.0) - 2023-05-15 + +### What's new +- Added support to wrap field in input group +- Added support to display error messages below the field +- Added support for floating labels for inputs. + +## [0.2.3](https://github.com/shivam091/rails_bootstrap_form/compare/v0.2.2...v0.2.3) - 2023-05-15 + +### What's new +- Added component to mark labels as required + +## [0.2.2](https://github.com/shivam091/rails_bootstrap_form/compare/v0.2.1...v0.2.2) - 2023-05-15 + +### What's new +- Added support to display labels along with the field. + +## [0.2.1](https://github.com/shivam091/rails_bootstrap_form/compare/v0.2.0...v0.2.1) - 2023-05-15 + +### What's new +- Added FieldWrapperBuilder to create wrapper for placing fields and other related components +- Added support to display help text along with the field +- Added wrapper methods for simple form fields + +## [0.2.0](https://github.com/shivam091/rails_bootstrap_form/compare/v0.1.1...v0.2.0) - 2023-05-15 + +### What's new +- Added PORO class `BootstrapFormOptions` to maintain gem specific configuration. +- Added BoostrapFormBuilder and extension methods for Rails form builder. +- Added required models, controllers, and views in demo application. + +## [0.1.1](https://github.com/shivam091/rails_bootstrap_form/compare/v0.1.0...v0.1.1) - 2023-05-15 + +### What's new +- Initialized demo application for demonstrating the working. +- Added generater to copy initializer file required for maintaining global configuration. +- Added Configuration class to maintain configurable options. + +## 0.1.0 - 2023-05-15 - Initial release + +## [Unreleased] diff --git a/Gemfile.lock b/Gemfile.lock index 14d0d56..0c7425f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,9 @@ PATH remote: . specs: - rails_bootstrap_form (0.6.0) + rails_bootstrap_form (0.6.1) + actionpack (~> 7.0) + activemodel (~> 7.0) GEM remote: http://rubygems.org/ @@ -79,6 +81,8 @@ GEM sassc-rails (>= 2.0.0) builder (3.2.4) byebug (11.1.3) + compare-xml (0.66) + nokogiri (~> 1.8) concurrent-ruby (1.2.2) crass (1.0.6) date (3.3.3) @@ -118,6 +122,7 @@ GEM nio4r (2.5.9) nokogiri (1.14.4-x86_64-linux) racc (~> 1.4) + pg (1.5.3) popper_js (2.11.7) puma (6.2.2) nio4r (~> 2.0) @@ -190,7 +195,6 @@ GEM actionpack (>= 5.2) activesupport (>= 5.2) sprockets (>= 3.0.0) - sqlite3 (1.6.2-x86_64-linux) thor (1.2.2) tilt (2.1.0) timeout (0.3.2) @@ -207,7 +211,10 @@ PLATFORMS DEPENDENCIES bootstrap (~> 5.3.0.alpha3) byebug + compare-xml generator_spec + nokogiri + pg (~> 1.1) puma rails (~> 7.0) rails_bootstrap_form! @@ -216,7 +223,6 @@ DEPENDENCIES sassc-rails simplecov sprockets-rails - sqlite3 (~> 1.4) BUNDLED WITH 2.4.10 diff --git a/README.md b/README.md index e69de29..20757a1 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,68 @@ +# RailsBootstrapForm + +**rails_bootstrap_form** is a Rails form builder that makes it super easy to integrate +[Bootstrap 5](https://getbootstrap.com/) forms into your Rails application. + +## Minimum Requirements + +* Ruby 3.2.2+ (https://www.ruby-lang.org/en/downloads/branches/) +* Rails 7.0+ (https://guides.rubyonrails.org/maintenance_policy.html) +* Bootstrap 5.0+ (https://getbootstrap.com/docs/versions/) + +## Installation + +Install Bootstrap 5. There are many ways to do this, depending on the asset pipeline you're using in your Rails application. One way is to use the gem that works with Sprockets. To do so, in a brand new Rails 7.0 application created _without_ the `--webpacker` option, add the `bootstrap` gem to your `Gemfile`: + +```ruby +gem "bootstrap", "~> 5.0" +``` + +And follow the remaining instructions in the [official bootstrap installation guide](https://github.com/twbs/bootstrap-rubygem#a-ruby-on-rails) for setting up `application.scss` and `application.js`. + +Add the `rails_bootstrap_form` gem to your `Gemfile`: + +```ruby +gem "rails_bootstrap_form", "~> 0.6.1" +``` + +Then: + +`bundle install` + +Depending on which CSS pre-processor you are using, adding the bootstrap form styles differs slightly. +If you use Rails in the default mode without any pre-processor, you'll have to add the following line to your `application.css` file: + +```css +*= require rails_bootstrap_form +``` + +If you followed the [official bootstrap installation guide](https://github.com/twbs/bootstrap-rubygem#a-ruby-on-rails), you'll probably have switched to SCSS. In this case add the following line to your `application.scss`: + +```scss +@import "rails_bootstrap_form"; +``` + +## Configuration + +`rails_bootstrap_form` can be used without any configuration. However, `rails_bootstrap_form` does have an optional configuration file at `config/initializers/rails_bootstrap_form.rb` for setting options that affect all generated forms in an application. This configuration file is created using the generator +by running the command on the terminal. + +``` +$ rails generate rails_bootstrap_form:install +``` + +Example: + +```ruby +# config/initializers/rails_bootstrap_form.rb +RailsBootstrapForm.configure do |config| + # to make forms non-compliant with W3C. + config.default_form_attributes = {role: "form", novalidate: true} +end +``` + +The current configuration options are: + +| Option | Default value | Description | +|---------------------------|------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `default_form_attributes` | | Set this option to `{role: "form"}` to make forms non-compliant with W3C, but generate the `role="form"` attribute. | diff --git a/Rakefile b/Rakefile index 888cabd..fccbf76 100644 --- a/Rakefile +++ b/Rakefile @@ -4,7 +4,9 @@ require "bundler/gem_tasks" require "rspec/core/rake_task" +require_relative "demo/config/application" +Rails.application.load_tasks RSpec::Core::RakeTask.new(:spec) task default: :spec diff --git a/demo/app/views/users/_horizontal_form.html.erb b/demo/app/views/users/_horizontal_form.html.erb index d2e989b..7ee8b3d 100644 --- a/demo/app/views/users/_horizontal_form.html.erb +++ b/demo/app/views/users/_horizontal_form.html.erb @@ -5,24 +5,24 @@
<%= bootstrap_form_for @user, bootstrap_form: {layout: :horizontal} do |form| %> <%= form.text_field :name, autocomplete: "new-name" %> - <%= form.text_field :email, autocomplete: "new-email" %> - <%= form.text_field :password, autocomplete: "new-password" %> + <%= form.email_field :email, autocomplete: "new-email" %> + <%= form.password_field :password, autocomplete: "new-password" %> <%= form.phone_field :mobile_number %> <%= form.date_field :birth_date %> - <%= form.radio_button :terms, 1, required: true %> <%= form.range_field :excellence %> <%= form.url_field :blog_url %> - <%= form.collection_radio_buttons :fruit_id, ::Fruit.all, :id, :name, {bootstrap_form: {}, checked: form.object.fruit_id} %> + <%= form.collection_radio_buttons :fruit_id, ::Fruit.all, :id, :name, {checked: form.object.fruit_id} %> <%= form.color_field :favorite_color %> - <%= form.collection_check_boxes :skill_ids, ::Skill.all, :id, :name, {bootstrap_form: {}} %> + <%= form.collection_check_boxes :skill_ids, ::Skill.all, :id, :name %> <%= form.fields_for :address, include_id: false, bootstrap_form: {layout: :horizontal} do |address_form| %> <%= address_form.text_area :street %> <%= address_form.text_field :state %> <%= address_form.grouped_collection_select :city, ::Country.includes(:cities), :cities, :name, :id, :name, {include_blank: "Select city"} %> <%= address_form.text_field :postal_code %> <%= address_form.select :country_id, options_for_select(::Country.pluck(:name, :id), address_form.object.country_id), - {include_blank: "Select Country", bootstrap_form: {}} %> + {include_blank: "Select Country"} %> <% end %> + <%= form.check_box :terms, required: true %>
<%= form.submit "Register", class: "btn btn-primary" %> <%= link_to "Cancel", users_path, class: "btn btn-secondary" %> diff --git a/demo/app/views/users/_vertical_form.html.erb b/demo/app/views/users/_vertical_form.html.erb index 0455fd9..0a736b9 100644 --- a/demo/app/views/users/_vertical_form.html.erb +++ b/demo/app/views/users/_vertical_form.html.erb @@ -3,26 +3,26 @@ Profile Form (Vertical layout)
- <%= bootstrap_form_for @user, bootstrap_form: {} do |form| %> - <%= form.text_field :name, autocomplete: "new-name", class: "dsds", bootstrap_form: {} %> - <%= form.text_field :email, autocomplete: "new-email", bootstrap_form: {} %> - <%= form.text_field :password, autocomplete: "new-password" %> + <%= bootstrap_form_for @user do |form| %> + <%= form.text_field :name, autocomplete: "new-name" %> + <%= form.email_field :email, autocomplete: "new-email" %> + <%= form.password_field :password, autocomplete: "new-password" %> <%= form.phone_field :mobile_number %> <%= form.date_field :birth_date %> - <%= form.check_box :terms, bootstrap_form: {switch: false}, required: true %> <%= form.range_field :excellence %> <%= form.url_field :blog_url %> - <%= form.collection_radio_buttons :fruit_id, ::Fruit.all, :id, :name, {bootstrap_form: {}, checked: form.object.fruit_id} %> + <%= form.collection_radio_buttons :fruit_id, ::Fruit.all, :id, :name, {checked: form.object.fruit_id} %> <%= form.color_field :favorite_color %> - <%= form.collection_check_boxes :skill_ids, ::Skill.all, :id, :name, {bootstrap_form: {}} %> + <%= form.collection_check_boxes :skill_ids, ::Skill.all, :id, :name %> <%= form.fields_for :address, include_id: false do |address_form| %> <%= address_form.text_area :street %> <%= address_form.text_field :state %> <%= address_form.grouped_collection_select :city, ::Country.includes(:cities), :cities, :name, :id, :name, {include_blank: "Select city"} %> <%= address_form.text_field :postal_code %> <%= address_form.select :country_id, options_for_select(::Country.pluck(:name, :id), address_form.object.country_id), - {include_blank: "Select Country", bootstrap_form: {}} %> + {include_blank: "Select Country"} %> <% end %> + <%= form.check_box :terms, required: true %>
<%= form.submit "Register", class: "btn btn-primary" %> <%= link_to "Cancel", users_path, class: "btn btn-secondary" %> diff --git a/demo/config/database.yml b/demo/config/database.yml index fcba57f..131e002 100644 --- a/demo/config/database.yml +++ b/demo/config/database.yml @@ -1,25 +1,17 @@ -# SQLite. Versions 3.8.0 and up are supported. -# gem install sqlite3 -# -# Ensure the SQLite 3 gem is defined in your Gemfile -# gem "sqlite3" -# default: &default - adapter: sqlite3 - pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> - timeout: 5000 + adapter: postgresql + encoding: unicode + reconnect: false + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 20 } %> development: <<: *default - database: db/development.sqlite3 + url: <%= ENV["DATABASE_URL"] %> -# Warning: The database defined as "test" will be erased and -# re-generated from your development database when you run "rake". -# Do not set this db to the same as development or production. test: <<: *default - database: db/test.sqlite3 + url: <%= ENV["DATABASE_URL"] %> production: <<: *default - database: db/production.sqlite3 + url: <%= ENV["DATABASE_URL"] %> diff --git a/demo/db/schema.rb b/demo/db/schema.rb index 00f67f6..87a69dc 100644 --- a/demo/db/schema.rb +++ b/demo/db/schema.rb @@ -11,8 +11,11 @@ # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema[7.0].define(version: 2023_05_16_044126) do + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + create_table "addresses", primary_key: "user_id", force: :cascade do |t| - t.integer "country_id" + t.bigint "country_id" t.string "street" t.string "city" t.string "state" @@ -25,7 +28,7 @@ create_table "cities", force: :cascade do |t| t.string "name" - t.integer "country_id" + t.bigint "country_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["country_id"], name: "index_cities_on_country_id" @@ -50,8 +53,8 @@ end create_table "user_skills", force: :cascade do |t| - t.integer "user_id" - t.integer "skill_id" + t.bigint "user_id" + t.bigint "skill_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["skill_id"], name: "index_user_skills_on_skill_id" @@ -65,7 +68,7 @@ t.string "mobile_number" t.string "blog_url" t.date "birth_date" - t.integer "fruit_id" + t.bigint "fruit_id" t.boolean "terms" t.string "excellence" t.string "favorite_color" diff --git a/gemfiles/common.gemfile b/gemfiles/common.gemfile index e390100..17a64ba 100644 --- a/gemfiles/common.gemfile +++ b/gemfiles/common.gemfile @@ -15,8 +15,8 @@ gem "sassc-rails" # Add bootstrap support gem "bootstrap", "~> 5.3.0.alpha3" -# Use sqlite3 as the database for Active Record -gem "sqlite3", "~> 1.4" +# Use postgresql as the database for Active Record +gem "pg", "~> 1.1" # Library to show coverage of the code. gem "simplecov" @@ -25,6 +25,14 @@ group :development do gem "puma" end +group :test do + # make it easy and painless to work with XML and HTML from Ruby. + gem "nokogiri" + + # Solve your XML/HTML comparison or diffing needs. + gem "compare-xml" +end + group :development, :test do gem "byebug" end diff --git a/lib/rails_bootstrap_form.rb b/lib/rails_bootstrap_form.rb index 3018058..f3b7e28 100644 --- a/lib/rails_bootstrap_form.rb +++ b/lib/rails_bootstrap_form.rb @@ -13,7 +13,6 @@ module RailsBootstrapForm autoload :Configuration autoload :BootstrapFormOptions autoload :BootstrapFormBuilder - autoload :Components autoload :FieldWrapperBuilder autoload :InputGroupBuilder autoload :Inputs @@ -23,7 +22,8 @@ module RailsBootstrapForm class << self def eager_load! super - RailsBootstrapForm::Components.eager_load! + RailsBootstrapForm::Helpers.eager_load! + RailsBootstrapForm::Inputs.eager_load! end def config diff --git a/lib/rails_bootstrap_form/bootstrap_form_builder.rb b/lib/rails_bootstrap_form/bootstrap_form_builder.rb index fde7888..2eef576 100644 --- a/lib/rails_bootstrap_form/bootstrap_form_builder.rb +++ b/lib/rails_bootstrap_form/bootstrap_form_builder.rb @@ -6,7 +6,7 @@ module RailsBootstrapForm class BootstrapFormBuilder < ActionView::Helpers::FormBuilder include RailsBootstrapForm::FieldWrapperBuilder - include RailsBootstrapForm::Components + include RailsBootstrapForm::Helpers include RailsBootstrapForm::InputGroupBuilder include RailsBootstrapForm::Inputs diff --git a/lib/rails_bootstrap_form/components.rb b/lib/rails_bootstrap_form/components.rb deleted file mode 100644 index f598db1..0000000 --- a/lib/rails_bootstrap_form/components.rb +++ /dev/null @@ -1,23 +0,0 @@ -# -*- encoding: utf-8 -*- -# -*- frozen_string_literal: true -*- -# -*- warn_indent: true -*- - -module RailsBootstrapForm - module Components - extend ActiveSupport::Autoload - - autoload :HelpText - autoload :Labels - autoload :RequiredField - autoload :Errors - autoload :CheckBox - autoload :RadioButton - - include HelpText - include Labels - include RequiredField - include Errors - include CheckBox - include RadioButton - end -end diff --git a/lib/rails_bootstrap_form/helpers.rb b/lib/rails_bootstrap_form/helpers.rb index f5582f7..3bf1ee6 100644 --- a/lib/rails_bootstrap_form/helpers.rb +++ b/lib/rails_bootstrap_form/helpers.rb @@ -5,6 +5,21 @@ module RailsBootstrapForm module Helpers extend ActiveSupport::Concern + extend ActiveSupport::Autoload + + autoload :HelpText + autoload :Labels + autoload :RequiredField + autoload :Errors + autoload :CheckBox + autoload :RadioButton + + include HelpText + include Labels + include RequiredField + include Errors + include CheckBox + include RadioButton def self.included(base_class) def collection_input_checked?(checked, obj, input_value) diff --git a/lib/rails_bootstrap_form/components/check_box.rb b/lib/rails_bootstrap_form/helpers/check_box.rb similarity index 98% rename from lib/rails_bootstrap_form/components/check_box.rb rename to lib/rails_bootstrap_form/helpers/check_box.rb index a936151..4651722 100644 --- a/lib/rails_bootstrap_form/components/check_box.rb +++ b/lib/rails_bootstrap_form/helpers/check_box.rb @@ -3,12 +3,10 @@ # -*- warn_indent: true -*- module RailsBootstrapForm - module Components + module Helpers module CheckBox extend ActiveSupport::Concern - include RailsBootstrapForm::Helpers - def self.included(base_class) def check_box_label(attribute, checked_value, options, bootstrap_options, &block) unless bootstrap_options.skip_label diff --git a/lib/rails_bootstrap_form/components/errors.rb b/lib/rails_bootstrap_form/helpers/errors.rb similarity index 99% rename from lib/rails_bootstrap_form/components/errors.rb rename to lib/rails_bootstrap_form/helpers/errors.rb index 2288a47..71e61a6 100644 --- a/lib/rails_bootstrap_form/components/errors.rb +++ b/lib/rails_bootstrap_form/helpers/errors.rb @@ -3,7 +3,7 @@ # -*- warn_indent: true -*- module RailsBootstrapForm - module Components + module Helpers module Errors extend ActiveSupport::Concern diff --git a/lib/rails_bootstrap_form/components/help_text.rb b/lib/rails_bootstrap_form/helpers/help_text.rb similarity index 98% rename from lib/rails_bootstrap_form/components/help_text.rb rename to lib/rails_bootstrap_form/helpers/help_text.rb index bcf0617..8782e75 100644 --- a/lib/rails_bootstrap_form/components/help_text.rb +++ b/lib/rails_bootstrap_form/helpers/help_text.rb @@ -3,7 +3,7 @@ # -*- warn_indent: true -*- module RailsBootstrapForm - module Components + module Helpers module HelpText extend ActiveSupport::Concern diff --git a/lib/rails_bootstrap_form/components/labels.rb b/lib/rails_bootstrap_form/helpers/labels.rb similarity index 98% rename from lib/rails_bootstrap_form/components/labels.rb rename to lib/rails_bootstrap_form/helpers/labels.rb index 36ef5b6..b49f124 100644 --- a/lib/rails_bootstrap_form/components/labels.rb +++ b/lib/rails_bootstrap_form/helpers/labels.rb @@ -3,7 +3,7 @@ # -*- warn_indent: true -*- module RailsBootstrapForm - module Components + module Helpers module Labels extend ActiveSupport::Concern diff --git a/lib/rails_bootstrap_form/components/radio_button.rb b/lib/rails_bootstrap_form/helpers/radio_button.rb similarity index 97% rename from lib/rails_bootstrap_form/components/radio_button.rb rename to lib/rails_bootstrap_form/helpers/radio_button.rb index ca7d65c..6dd0607 100644 --- a/lib/rails_bootstrap_form/components/radio_button.rb +++ b/lib/rails_bootstrap_form/helpers/radio_button.rb @@ -3,12 +3,10 @@ # -*- warn_indent: true -*- module RailsBootstrapForm - module Components + module Helpers module RadioButton extend ActiveSupport::Concern - include RailsBootstrapForm::Helpers - def self.included(base_class) def radio_button_label(attribute, value, options, bootstrap_options) unless bootstrap_options.skip_label diff --git a/lib/rails_bootstrap_form/components/required_field.rb b/lib/rails_bootstrap_form/helpers/required_field.rb similarity index 99% rename from lib/rails_bootstrap_form/components/required_field.rb rename to lib/rails_bootstrap_form/helpers/required_field.rb index 048ba59..7cb7c42 100644 --- a/lib/rails_bootstrap_form/components/required_field.rb +++ b/lib/rails_bootstrap_form/helpers/required_field.rb @@ -3,7 +3,7 @@ # -*- warn_indent: true -*- module RailsBootstrapForm - module Components + module Helpers module RequiredField extend ActiveSupport::Concern diff --git a/lib/rails_bootstrap_form/inputs.rb b/lib/rails_bootstrap_form/inputs.rb index 62e79b0..b4fda6c 100644 --- a/lib/rails_bootstrap_form/inputs.rb +++ b/lib/rails_bootstrap_form/inputs.rb @@ -3,241 +3,73 @@ # -*- warn_indent: true -*- module RailsBootstrapForm - include Helpers - module Inputs - FIELD_HELPERS = %i[ - text_field - url_field - search_field - telephone_field - number_field - email_field - file_field - phone_field - password_field - text_area - date_field - time_field - datetime_field - datetime_local_field - month_field - week_field - ].freeze - - DATE_SELECT_HELPERS = %i[ - date_select - time_select - datetime_select - ].freeze - - FIELD_HELPERS.each do |field_tag_name| - define_method(field_tag_name) do |attribute, options = {}| - field_wrapper_builder(attribute, options) do - super(attribute, options) - end - end - end - - DATE_SELECT_HELPERS.each do |field_tag_name| - define_method(field_tag_name) do |attribute, options = {}, html_options = {}| - options = {bootstrap_form: {field_class: "form-select"}}.deep_merge!(options) - - field_wrapper_builder(attribute, options, html_options) do - tag.div(class: control_specific_class(field_tag_name)) do - super(attribute, options, html_options) - end - end - end - end - - def select(attribute, choices = nil, options = {}, html_options = {}, &block) - options = {bootstrap_form: {field_class: "form-select"}}.deep_merge!(options) - - field_wrapper_builder(attribute, options, html_options) do - super(attribute, choices, options, html_options, &block) - end - end - - def collection_select(attribute, collection, value_method, text_method, options = {}, html_options = {}) - options = {bootstrap_form: {field_class: "form-select"}}.deep_merge!(options) - - field_wrapper_builder(attribute, options, html_options) do - super(attribute, collection, value_method, text_method, options, html_options) - end - end - - def grouped_collection_select(attribute, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {}) - options = {bootstrap_form: {field_class: "form-select"}}.deep_merge!(options) - - field_wrapper_builder(attribute, options, html_options) do - super(attribute, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options) - end - end - - def time_zone_select(attribute, priority_zones = nil, options = {}, html_options = {}) - options = {bootstrap_form: {field_class: "form-select"}}.deep_merge!(options) - - field_wrapper_builder(attribute, options, html_options) do - super(attribute, priority_zones, options, html_options) - end - end - - def range_field(attribute, options = {}) - options = {bootstrap_form: {field_class: "form-range"}}.deep_merge!(options) - - field_wrapper_builder(attribute, options) do - super(attribute, options) - end - end - - def color_field(attribute, options = {}) - options = {bootstrap_form: {field_class: "form-control form-control-color"}}.deep_merge!(options) - - field_wrapper_builder(attribute, options) do - super(attribute, options) - end - end - - def hidden_field(attribute, options = {}) - options[:value] = object.send(attribute) unless options.key?(:value) - - super(attribute, options) - end - - def static_field(*args) - options = args.extract_options! - attribute = args.first - - static_options = options.merge( - readonly: true, - disabled: true, - bootstrap_form: { - field_class: bootstrap_form_options.static_field_class - } - ) - - static_options[:value] = object.send(attribute) unless options.key?(:value) - - text_field(attribute, static_options) - end - - def check_box(attribute, options = {}, checked_value = "1", unchecked_value = "0", &block) - bootstrap_options = bootstrap_form_options.scoped(options.delete(:bootstrap_form)) - - options[:class] = check_box_classes(attribute, options) - - check_box_field = super(attribute, options, checked_value, unchecked_value) - check_box_help_text = help_text(attribute, bootstrap_options) - - check_box_label = check_box_label(attribute, checked_value, options, bootstrap_options, &block) - - check_box_html = tag.div(**check_box_wrapper_options(bootstrap_options)) do - concat(check_box_field) - concat(check_box_label) - concat(check_box_help_text) unless bootstrap_options.inline? - concat(generate_error(attribute)) if (is_invalid?(attribute) && !bootstrap_options.inline?) - end - - if bootstrap_options.inline? - check_box_html - else - if bootstrap_options.layout_horizontal? - tag.div(class: field_wrapper_classes(bootstrap_options)) do - tag.div(class: check_box_container_classes(bootstrap_options)) do - check_box_html - end - end - else - check_box_html - end - end - end - - def radio_button(attribute, value, options = {}) - bootstrap_options = bootstrap_form_options.scoped(options.delete(:bootstrap_form)) - - options[:class] = radio_button_classes(attribute, options) - - radio_button_field = super(attribute, value, options) - radio_button_help_text = help_text(attribute, bootstrap_options) - - radio_button_label = radio_button_label(attribute, value, options, bootstrap_options) - - radio_button_html = tag.div(**radio_button_wrapper_options(bootstrap_options)) do - concat(radio_button_field) - concat(radio_button_label) - concat(radio_button_help_text) unless bootstrap_options.inline? - concat(generate_error(attribute)) if (is_invalid?(attribute) && !bootstrap_options.inline?) - end - - if bootstrap_options.inline? - radio_button_html - else - if bootstrap_options.layout_horizontal? - tag.div(class: field_wrapper_classes(bootstrap_options)) do - tag.div(class: radio_button_container_classes(bootstrap_options)) do - radio_button_html - end - end - else - radio_button_html - end - end - end - - def collection_check_boxes(attribute, collection, value_method, text_method, options = {}, html_options = {}, &block) - options[:multiple] = true - - inputs = ActiveSupport::SafeBuffer.new - - collection.each do |object| - input_value = value_method.respond_to?(:call) ? value_method.call(object) : object.send(value_method) - input_options = { - bootstrap_form: { - label_text: text_method.respond_to?(:call) ? text_method.call(object) : object.send(text_method), - inline: true - } - }.deep_merge!(options) - - inputs << check_box(attribute, input_options, input_value, nil) - end - - if options.delete(:include_hidden) { true } - inputs.prepend(hidden_field(attribute, value: "", multiple: options[:multiple])) - end - - field_wrapper_builder(attribute, options, html_options) do - concat(tag.div(class: control_specific_class(:collection_check_boxes)) do - concat(inputs) - end) - end - end - - def collection_radio_buttons(attribute, collection, value_method, text_method, options = {}, html_options = {}, &block) - inputs = ActiveSupport::SafeBuffer.new - - collection.each do |object| - input_value = value_method.respond_to?(:call) ? value_method.call(object) : object.send(value_method) - input_options = { - bootstrap_form: { - label_text: text_method.respond_to?(:call) ? text_method.call(object) : object.send(text_method), - inline: true - } - }.deep_merge!(options) - - if (checked = input_options[:checked]) - input_options[:checked] = collection_input_checked?(checked, object, object.send(value_method)) - end - - inputs << radio_button(attribute, input_value, input_options) - end - - field_wrapper_builder(attribute, options, html_options) do - concat(tag.div(class: control_specific_class(:collection_radio_buttons)) do - concat(inputs) - end) - end - end + extend ActiveSupport::Autoload + + autoload :Base + autoload :CheckBox + autoload :CollectionCheckBoxes + autoload :CollectionRadioButtons + autoload :CollectionSelect + autoload :ColorField + autoload :DateField + autoload :DateSelect + autoload :DatetimeField + autoload :DatetimeLocalField + autoload :DatetimeSelect + autoload :EmailField + autoload :FileField + autoload :GroupedCollectionSelect + autoload :HiddenField + autoload :MonthField + autoload :NumberField + autoload :PasswordField + autoload :PhoneField + autoload :RadioButton + autoload :RangeField + autoload :SearchField + autoload :Select + autoload :StaticField + autoload :TelephoneField + autoload :TextArea + autoload :TextField + autoload :TimeField + autoload :TimeSelect + autoload :TimeZoneSelect + autoload :UrlField + autoload :WeekField + + include Base + include CheckBox + include CollectionCheckBoxes + include CollectionRadioButtons + include CollectionSelect + include ColorField + include DateField + include DateSelect + include DatetimeField + include DatetimeLocalField + include DatetimeSelect + include EmailField + include FileField + include GroupedCollectionSelect + include HiddenField + include MonthField + include NumberField + include PasswordField + include PhoneField + include RadioButton + include RangeField + include SearchField + include Select + include StaticField + include TelephoneField + include TextArea + include TextField + include TimeField + include TimeSelect + include TimeZoneSelect + include UrlField + include WeekField end end diff --git a/lib/rails_bootstrap_form/inputs/base.rb b/lib/rails_bootstrap_form/inputs/base.rb new file mode 100644 index 0000000..41c9ed1 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/base.rb @@ -0,0 +1,33 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module Base + extend ActiveSupport::Concern + + class_methods do + def bootstrap_field(field_name) + define_method(field_name) do |attribute, options = {}| + field_wrapper_builder(attribute, options) do + super(attribute, options) + end + end + end + + def bootstrap_select_group(field_name) + define_method(field_name) do |attribute, options = {}, html_options = {}| + options = {bootstrap_form: {field_class: "form-select"}}.deep_merge!(options) + + field_wrapper_builder(attribute, options, html_options) do + tag.div(class: control_specific_class(field_name)) do + super(attribute, options, html_options) + end + end + end + end + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/check_box.rb b/lib/rails_bootstrap_form/inputs/check_box.rb new file mode 100644 index 0000000..c74e5f3 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/check_box.rb @@ -0,0 +1,45 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module CheckBox + extend ActiveSupport::Concern + + included do + def check_box(attribute, options = {}, checked_value = "1", unchecked_value = "0", &block) + bootstrap_options = bootstrap_form_options.scoped(options.delete(:bootstrap_form)) + + options[:class] = check_box_classes(attribute, options) + + check_box_field = super(attribute, options, checked_value, unchecked_value) + check_box_help_text = help_text(attribute, bootstrap_options) + + check_box_label = check_box_label(attribute, checked_value, options, bootstrap_options, &block) + + check_box_html = tag.div(**check_box_wrapper_options(bootstrap_options)) do + concat(check_box_field) + concat(check_box_label) + concat(check_box_help_text) unless bootstrap_options.inline? + concat(generate_error(attribute)) if (is_invalid?(attribute) && !bootstrap_options.inline?) + end + + if bootstrap_options.inline? + check_box_html + else + if bootstrap_options.layout_horizontal? + tag.div(class: field_wrapper_classes(bootstrap_options)) do + tag.div(class: check_box_container_classes(bootstrap_options)) do + check_box_html + end + end + else + check_box_html + end + end + end + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/collection_check_boxes.rb b/lib/rails_bootstrap_form/inputs/collection_check_boxes.rb new file mode 100644 index 0000000..a46ad2b --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/collection_check_boxes.rb @@ -0,0 +1,41 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module CollectionCheckBoxes + extend ActiveSupport::Concern + + included do + def collection_check_boxes(attribute, collection, value_method, text_method, options = {}, html_options = {}, &block) + options[:multiple] = true + + inputs = ActiveSupport::SafeBuffer.new + + collection.each do |object| + input_value = value_method.respond_to?(:call) ? value_method.call(object) : object.send(value_method) + input_options = { + bootstrap_form: { + label_text: text_method.respond_to?(:call) ? text_method.call(object) : object.send(text_method), + inline: true + } + }.deep_merge!(options) + + inputs << check_box(attribute, input_options, input_value, nil) + end + + if options.delete(:include_hidden) { true } + inputs.prepend(hidden_field(attribute, value: "", multiple: options[:multiple])) + end + + field_wrapper_builder(attribute, options, html_options) do + concat(tag.div(class: control_specific_class(:collection_check_boxes)) do + concat(inputs) + end) + end + end + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/collection_radio_buttons.rb b/lib/rails_bootstrap_form/inputs/collection_radio_buttons.rb new file mode 100644 index 0000000..829187e --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/collection_radio_buttons.rb @@ -0,0 +1,39 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module CollectionRadioButtons + extend ActiveSupport::Concern + + included do + def collection_radio_buttons(attribute, collection, value_method, text_method, options = {}, html_options = {}, &block) + inputs = ActiveSupport::SafeBuffer.new + + collection.each do |object| + input_value = value_method.respond_to?(:call) ? value_method.call(object) : object.send(value_method) + input_options = { + bootstrap_form: { + label_text: text_method.respond_to?(:call) ? text_method.call(object) : object.send(text_method), + inline: true + } + }.deep_merge!(options) + + if (checked = input_options[:checked]) + input_options[:checked] = collection_input_checked?(checked, object, object.send(value_method)) + end + + inputs << radio_button(attribute, input_value, input_options) + end + + field_wrapper_builder(attribute, options, html_options) do + concat(tag.div(class: control_specific_class(:collection_radio_buttons)) do + concat(inputs) + end) + end + end + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/collection_select.rb b/lib/rails_bootstrap_form/inputs/collection_select.rb new file mode 100644 index 0000000..54eb0e6 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/collection_select.rb @@ -0,0 +1,21 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module CollectionSelect + extend ActiveSupport::Concern + + included do + def collection_select(attribute, collection, value_method, text_method, options = {}, html_options = {}) + options = {bootstrap_form: {field_class: "form-select"}}.deep_merge!(options) + + field_wrapper_builder(attribute, options, html_options) do + super(attribute, collection, value_method, text_method, options, html_options) + end + end + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/color_field.rb b/lib/rails_bootstrap_form/inputs/color_field.rb new file mode 100644 index 0000000..1172701 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/color_field.rb @@ -0,0 +1,21 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module ColorField + extend ActiveSupport::Concern + + included do + def color_field(attribute, options = {}) + options = {bootstrap_form: {field_class: "form-control form-control-color"}}.deep_merge!(options) + + field_wrapper_builder(attribute, options) do + super(attribute, options) + end + end + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/date_field.rb b/lib/rails_bootstrap_form/inputs/date_field.rb new file mode 100644 index 0000000..c7e003c --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/date_field.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module DateField + extend ActiveSupport::Concern + + included do + bootstrap_field :date_field + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/date_select.rb b/lib/rails_bootstrap_form/inputs/date_select.rb new file mode 100644 index 0000000..63abf68 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/date_select.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module DateSelect + extend ActiveSupport::Concern + + included do + bootstrap_select_group :date_select + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/datetime_field.rb b/lib/rails_bootstrap_form/inputs/datetime_field.rb new file mode 100644 index 0000000..9716e07 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/datetime_field.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module DatetimeField + extend ActiveSupport::Concern + + included do + bootstrap_field :datetime_field + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/datetime_local_field.rb b/lib/rails_bootstrap_form/inputs/datetime_local_field.rb new file mode 100644 index 0000000..1bc1e1b --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/datetime_local_field.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module DatetimeLocalField + extend ActiveSupport::Concern + + included do + bootstrap_field :datetime_local_field + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/datetime_select.rb b/lib/rails_bootstrap_form/inputs/datetime_select.rb new file mode 100644 index 0000000..4179e0f --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/datetime_select.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module DatetimeSelect + extend ActiveSupport::Concern + + included do + bootstrap_select_group :datetime_select + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/email_field.rb b/lib/rails_bootstrap_form/inputs/email_field.rb new file mode 100644 index 0000000..2426b50 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/email_field.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module EmailField + extend ActiveSupport::Concern + + included do + bootstrap_field :email_field + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/file_field.rb b/lib/rails_bootstrap_form/inputs/file_field.rb new file mode 100644 index 0000000..7db538b --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/file_field.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module FileField + extend ActiveSupport::Concern + + included do + bootstrap_field :file_field + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/grouped_collection_select.rb b/lib/rails_bootstrap_form/inputs/grouped_collection_select.rb new file mode 100644 index 0000000..c8bf715 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/grouped_collection_select.rb @@ -0,0 +1,21 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module GroupedCollectionSelect + extend ActiveSupport::Concern + + included do + def grouped_collection_select(attribute, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {}) + options = {bootstrap_form: {field_class: "form-select"}}.deep_merge!(options) + + field_wrapper_builder(attribute, options, html_options) do + super(attribute, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options) + end + end + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/hidden_field.rb b/lib/rails_bootstrap_form/inputs/hidden_field.rb new file mode 100644 index 0000000..7ce5a79 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/hidden_field.rb @@ -0,0 +1,19 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module HiddenField + extend ActiveSupport::Concern + + included do + def hidden_field(attribute, options = {}) + options[:value] = object.send(attribute) unless options.key?(:value) + + super(attribute, options) + end + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/month_field.rb b/lib/rails_bootstrap_form/inputs/month_field.rb new file mode 100644 index 0000000..d1aec66 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/month_field.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module MonthField + extend ActiveSupport::Concern + + included do + bootstrap_field :month_field + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/number_field.rb b/lib/rails_bootstrap_form/inputs/number_field.rb new file mode 100644 index 0000000..b7b1b24 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/number_field.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module NumberField + extend ActiveSupport::Concern + + included do + bootstrap_field :number_field + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/password_field.rb b/lib/rails_bootstrap_form/inputs/password_field.rb new file mode 100644 index 0000000..b9452f4 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/password_field.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module PasswordField + extend ActiveSupport::Concern + + included do + bootstrap_field :password_field + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/phone_field.rb b/lib/rails_bootstrap_form/inputs/phone_field.rb new file mode 100644 index 0000000..b3fbb93 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/phone_field.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module PhoneField + extend ActiveSupport::Concern + + included do + bootstrap_field :phone_field + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/radio_button.rb b/lib/rails_bootstrap_form/inputs/radio_button.rb new file mode 100644 index 0000000..76d7f4b --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/radio_button.rb @@ -0,0 +1,45 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module RadioButton + extend ActiveSupport::Concern + + included do + def radio_button(attribute, value, options = {}) + bootstrap_options = bootstrap_form_options.scoped(options.delete(:bootstrap_form)) + + options[:class] = radio_button_classes(attribute, options) + + radio_button_field = super(attribute, value, options) + radio_button_help_text = help_text(attribute, bootstrap_options) + + radio_button_label = radio_button_label(attribute, value, options, bootstrap_options) + + radio_button_html = tag.div(**radio_button_wrapper_options(bootstrap_options)) do + concat(radio_button_field) + concat(radio_button_label) + concat(radio_button_help_text) unless bootstrap_options.inline? + concat(generate_error(attribute)) if (is_invalid?(attribute) && !bootstrap_options.inline?) + end + + if bootstrap_options.inline? + radio_button_html + else + if bootstrap_options.layout_horizontal? + tag.div(class: field_wrapper_classes(bootstrap_options)) do + tag.div(class: radio_button_container_classes(bootstrap_options)) do + radio_button_html + end + end + else + radio_button_html + end + end + end + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/range_field.rb b/lib/rails_bootstrap_form/inputs/range_field.rb new file mode 100644 index 0000000..caa901e --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/range_field.rb @@ -0,0 +1,21 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module RangeField + extend ActiveSupport::Concern + + included do + def range_field(attribute, options = {}) + options = {bootstrap_form: {field_class: "form-range"}}.deep_merge!(options) + + field_wrapper_builder(attribute, options) do + super(attribute, options) + end + end + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/search_field.rb b/lib/rails_bootstrap_form/inputs/search_field.rb new file mode 100644 index 0000000..bdd8645 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/search_field.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module SearchField + extend ActiveSupport::Concern + + included do + bootstrap_field :search_field + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/select.rb b/lib/rails_bootstrap_form/inputs/select.rb new file mode 100644 index 0000000..f3e5e43 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/select.rb @@ -0,0 +1,21 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module Select + extend ActiveSupport::Concern + + included do + def select(attribute, choices = nil, options = {}, html_options = {}, &block) + options = {bootstrap_form: {field_class: "form-select"}}.deep_merge!(options) + + field_wrapper_builder(attribute, options, html_options) do + super(attribute, choices, options, html_options, &block) + end + end + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/static_field.rb b/lib/rails_bootstrap_form/inputs/static_field.rb new file mode 100644 index 0000000..0a50819 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/static_field.rb @@ -0,0 +1,30 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module StaticField + extend ActiveSupport::Concern + + included do + def static_field(*args) + options = args.extract_options! + attribute = args.first + + static_options = options.merge( + readonly: true, + disabled: true, + bootstrap_form: { + field_class: bootstrap_form_options.static_field_class + } + ) + + static_options[:value] = object.send(attribute) unless options.key?(:value) + + text_field(attribute, static_options) + end + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/telephone_field.rb b/lib/rails_bootstrap_form/inputs/telephone_field.rb new file mode 100644 index 0000000..eab2183 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/telephone_field.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module TelephoneField + extend ActiveSupport::Concern + + included do + bootstrap_field :telephone_field + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/text_area.rb b/lib/rails_bootstrap_form/inputs/text_area.rb new file mode 100644 index 0000000..5d00d58 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/text_area.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module TextArea + extend ActiveSupport::Concern + + included do + bootstrap_field :text_area + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/text_field.rb b/lib/rails_bootstrap_form/inputs/text_field.rb new file mode 100644 index 0000000..b42d5c2 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/text_field.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module TextField + extend ActiveSupport::Concern + + included do + bootstrap_field :text_field + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/time_field.rb b/lib/rails_bootstrap_form/inputs/time_field.rb new file mode 100644 index 0000000..0327990 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/time_field.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module TimeField + extend ActiveSupport::Concern + + included do + bootstrap_field :time_field + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/time_select.rb b/lib/rails_bootstrap_form/inputs/time_select.rb new file mode 100644 index 0000000..ef85b82 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/time_select.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module TimeSelect + extend ActiveSupport::Concern + + included do + bootstrap_select_group :time_select + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/time_zone_select.rb b/lib/rails_bootstrap_form/inputs/time_zone_select.rb new file mode 100644 index 0000000..f9ed2b7 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/time_zone_select.rb @@ -0,0 +1,21 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module TimeZoneSelect + extend ActiveSupport::Concern + + included do + def time_zone_select(attribute, priority_zones = nil, options = {}, html_options = {}) + options = {bootstrap_form: {field_class: "form-select"}}.deep_merge!(options) + + field_wrapper_builder(attribute, options, html_options) do + super(attribute, priority_zones, options, html_options) + end + end + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/url_field.rb b/lib/rails_bootstrap_form/inputs/url_field.rb new file mode 100644 index 0000000..99d0d66 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/url_field.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module UrlField + extend ActiveSupport::Concern + + included do + bootstrap_field :url_field + end + end + end +end diff --git a/lib/rails_bootstrap_form/inputs/week_field.rb b/lib/rails_bootstrap_form/inputs/week_field.rb new file mode 100644 index 0000000..ca4cbc5 --- /dev/null +++ b/lib/rails_bootstrap_form/inputs/week_field.rb @@ -0,0 +1,15 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +module RailsBootstrapForm + module Inputs + module WeekField + extend ActiveSupport::Concern + + included do + bootstrap_field :week_field + end + end + end +end diff --git a/lib/rails_bootstrap_form/version.rb b/lib/rails_bootstrap_form/version.rb index 14fed27..76a67bc 100644 --- a/lib/rails_bootstrap_form/version.rb +++ b/lib/rails_bootstrap_form/version.rb @@ -3,6 +3,6 @@ # -*- warn_indent: true -*- module RailsBootstrapForm - VERSION = "0.6.0".freeze + VERSION = "0.6.1".freeze REQUIRED_RAILS_VERSION = "~> 7.0".freeze end diff --git a/rails_bootstrap_form.gemspec b/rails_bootstrap_form.gemspec index 18357af..b9824eb 100644 --- a/rails_bootstrap_form.gemspec +++ b/rails_bootstrap_form.gemspec @@ -20,7 +20,7 @@ Gem::Specification.new do |spec| spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = "https://github.com/shivam091/rails_bootstrap_form" - spec.metadata["changelog_uri"] = "https://github.com/shivam091/rails_bootstrap_form/CHANGELOG.md" + spec.metadata["changelog_uri"] = "https://github.com/shivam091/rails_bootstrap_form/blob/main/CHANGELOG.md" # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. @@ -33,5 +33,7 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_development_dependency "generator_spec" + spec.add_development_dependency("generator_spec") + spec.add_dependency("actionpack", RailsBootstrapForm::REQUIRED_RAILS_VERSION) + spec.add_dependency("activemodel", RailsBootstrapForm::REQUIRED_RAILS_VERSION) end diff --git a/spec/rails_bootstrap_form/bootstrap_form_layout_spec.rb b/spec/rails_bootstrap_form/bootstrap_form_layout_spec.rb new file mode 100644 index 0000000..8e9b274 --- /dev/null +++ b/spec/rails_bootstrap_form/bootstrap_form_layout_spec.rb @@ -0,0 +1,124 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +# spec/rails_bootstrap_form/bootstrap_form_layout_spec.rb + +require "spec_helper" + +RSpec.describe RailsBootstrapForm::BootstrapFormBuilder do + it "checks markup of vertical form" do + expected = <<~HTML.strip_heredoc +
+
+ + +
+
+ + +
Please use official email address
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + +
You must first accept terms and conditions in order to continue
+
+
+ HTML + + actual = bootstrap_form_with(model: @user, url: "/test") do |form| + concat(form.text_field(:name)) + concat(form.email_field(:email)) + concat(form.password_field(:password)) + concat(form.date_field(:birth_date)) + concat(form.range_field(:excellence)) + concat(form.color_field(:favorite_color)) + concat(form.check_box(:terms)) + end + + expect(actual).to match_html(expected) + end + + it "checks markup of horizontal form" do + expected = <<~HTML.strip_heredoc +
+
+ +
+ +
+
+
+ +
+ +
Please use official email address
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+ + + +
+
+
+
+ HTML + + actual = bootstrap_form_with(model: @user, url: "/test", bootstrap_form: {layout: :horizontal}) do |form| + concat(form.text_field(:name)) + concat(form.email_field(:email)) + concat(form.password_field(:password)) + concat(form.date_field(:birth_date)) + concat(form.range_field(:excellence)) + concat(form.color_field(:favorite_color)) + concat(form.check_box(:term)) + end + + expect(actual).to match_html(expected) + end +end diff --git a/spec/rails_bootstrap_form/bootstrap_form_options_spec.rb b/spec/rails_bootstrap_form/bootstrap_form_options_spec.rb new file mode 100644 index 0000000..f2298a6 --- /dev/null +++ b/spec/rails_bootstrap_form/bootstrap_form_options_spec.rb @@ -0,0 +1,121 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +# spec/rails_bootstrap_form/bootstrap_form_options_spec.rb + +require "spec_helper" + +RSpec.describe RailsBootstrapForm::BootstrapFormOptions do + + describe "#set_defaults" do + let(:options) { described_class.new } + + it "sets default values of bootstrap form options" do + expect(options.layout).to eq("vertical") + expect(options.field_class).to eq("form-control") + expect(options.additional_field_class).to be_nil + expect(options.help_text).to be_nil + expect(options.label_text).to be_nil + expect(options.skip_label).to be_falsy + expect(options.hide_label).to be_falsy + expect(options.hide_class).to eq("visually-hidden") + expect(options.label_class).to eq("form-label") + expect(options.additional_label_class).to be_nil + expect(options.floating).to be_falsy + expect(options.static_field_class).to eq("form-control-plaintext") + expect(options.switch).to be_falsy + expect(options.wrapper_options).to eq({}) + expect(options.size).to be_nil + expect(options.inline).to be_falsy + expect(options.label_col_class).to eq("col-form-label") + expect(options.label_col_wrapper_class).to eq("col-sm-2") + expect(options.field_col_wrapper_class).to eq("col-sm-10") + end + end + + describe "#set_bootstrap_form_options" do + let(:options) do + options = described_class.new( + layout: "horizontal", + field_class: "form-select", + additional_field_class: "custom-class", + help_text: "This is help text", + label_text: "Test label", + skip_label: false, + hide_label: true, + hide_class: "sr-only", + label_class: "col-form-label", + additional_label_class: "form-label", + floating: true, + static_field_class: "form-control-plaintext", + switch: true, + wrapper_options: {data: {controller: "hello"}}, + size: :sm, + inline: true, + label_col_class: "col-form-label", + label_col_wrapper_class: "col-sm-3", + field_col_wrapper_class: "col-sm-9", + ) + end + + it "sets custom values of bootstrap form options" do + expect(options.layout).to eq("horizontal") + expect(options.field_class).to eq("form-select") + expect(options.additional_field_class).to eq("custom-class") + expect(options.help_text).to eq("This is help text") + expect(options.label_text).to eq("Test label") + expect(options.skip_label).to be_falsy + expect(options.hide_label).to be_truthy + expect(options.hide_class).to eq("sr-only") + expect(options.label_class).to eq("col-form-label") + expect(options.additional_label_class).to eq("form-label") + expect(options.floating).to be_truthy + expect(options.static_field_class).to eq("form-control-plaintext") + expect(options.switch).to be_truthy + expect(options.wrapper_options).to eq(data: {controller: "hello"}) + expect(options.size).to eq(:sm) + expect(options.inline).to be_truthy + expect(options.label_col_class).to eq("col-form-label") + expect(options.label_col_wrapper_class).to eq("col-sm-3") + expect(options.field_col_wrapper_class).to eq("col-sm-9") + end + end + + describe "#scoped" do + it "sets scoped values of bootstrap form options" do + options = described_class.new + expect(options.layout_horizontal?).to be_falsy + + scoped_options = options.scoped(layout: :horizontal) + expect(scoped_options.layout_horizontal?).to be_truthy + end + end + + describe "#vertical?" do + it "checks whether form has vertical layout" do + options = described_class.new + expect(options.layout_vertical?).to be_truthy + end + end + + describe "#horizontal?" do + it "checks whether form has horizontal layout" do + options = described_class.new + expect(options.layout_horizontal?).to be_falsy + + options = described_class.new(layout: :horizontal) + expect(options.layout_horizontal?).to be_truthy + end + end + + describe "#inline?" do + it "checks whether form has inline layout" do + options = described_class.new + expect(options.layout_inline?).to be_falsy + + options = described_class.new(layout: :inline) + expect(options.layout_inline?).to be_truthy + end + end +end diff --git a/spec/rails_bootstrap_form/inputs/text_field_spec.rb b/spec/rails_bootstrap_form/inputs/text_field_spec.rb new file mode 100644 index 0000000..9fbba1c --- /dev/null +++ b/spec/rails_bootstrap_form/inputs/text_field_spec.rb @@ -0,0 +1,283 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +# spec/rails_bootstrap_form/inputs/text_field_spec.rb + +require "spec_helper" + +RSpec.describe RailsBootstrapForm::Inputs::TextField do + describe "#text_field" do + it "renders text field correctly in vertical layout" do + expected = <<~HTML.strip_heredoc +
+ + +
+ HTML + + actual = @vertical_builder.text_field :name + + expect(actual).to match_html(expected) + end + + it "renders text field correctly in horizontal layout" do + expected = <<~HTML.strip_heredoc +
+ +
+ +
+
+ HTML + + actual = @horizontal_builder.text_field :name + + expect(actual).to match_html(expected) + end + + it "supports floating labels in vertical layout" do + expected = <<~HTML.strip_heredoc +
+
+ + +
+
+ HTML + + actual = @vertical_builder.text_field :name, bootstrap_form: {floating: true} + + expect(actual).to match_html(expected) + end + + it "does not support floating labels for horizontal layout" do + expected = <<~HTML.strip_heredoc +
+ +
+ +
+
+ HTML + + actual = @horizontal_builder.text_field :name, bootstrap_form: {floating: true} + + expect(actual).to match_html(expected) + end + + it "skips label of the field" do + expected = <<~HTML.strip_heredoc +
+ +
+ HTML + + actual = @vertical_builder.text_field :name, bootstrap_form: {skip_label: true} + + expect(actual).to match_html(expected) + end + + it "hides label of the field" do + expected = <<~HTML.strip_heredoc +
+ + +
+ HTML + + actual = @vertical_builder.text_field :name, bootstrap_form: {hide_label: true} + + expect(actual).to match_html(expected) + end + + it "adds additional css class to the field" do + expected = <<~HTML.strip_heredoc +
+ + +
+ HTML + + actual = @vertical_builder.text_field :name, bootstrap_form: {additional_field_class: "custom-class"} + + expect(actual).to match_html(expected) + end + + it "adds additional css class to a label of the field" do + expected = <<~HTML.strip_heredoc +
+ + +
+ HTML + + actual = @vertical_builder.text_field :name, bootstrap_form: {additional_label_class: "custom-class"} + + expect(actual).to match_html(expected) + end + + it "changes css class of the field" do + expected = <<~HTML.strip_heredoc +
+ + +
+ HTML + + actual = @vertical_builder.text_field :name, bootstrap_form: {field_class: "custom-form-control"} + + expect(actual).to match_html(expected) + end + + it "changes css class of the label" do + expected = <<~HTML.strip_heredoc +
+ + +
+ HTML + + actual = @vertical_builder.text_field :name, bootstrap_form: {label_class: "custom-form-label"} + + expect(actual).to match_html(expected) + end + + it "adds help text to the field" do + expected = <<~HTML.strip_heredoc +
+ + +
Please provide your full name
+
+ HTML + + actual = @vertical_builder.text_field :name, bootstrap_form: {help_text: "Please provide your full name"} + + expect(actual).to match_html(expected) + end + + it "displays help text from locale file" do + expected = <<~HTML.strip_heredoc +
+ + +
Please use official email address
+
+ HTML + + actual = @vertical_builder.text_field :email + + expect(actual).to match_html(expected) + end + + it "sets customize label text" do + expected = <<~HTML.strip_heredoc +
+ + +
+ HTML + + actual = @vertical_builder.text_field :name, bootstrap_form: {label_text: "Full name"} + + expect(actual).to match_html(expected) + end + + it "adds additional wrapper options" do + expected = <<~HTML.strip_heredoc +
+ + +
+ HTML + + actual = @vertical_builder.text_field :name, bootstrap_form: {wrapper_options: {data: {controller: "hello"}}} + + expect(actual).to match_html(expected) + end + + it "supports input group" do + expected = <<~HTML.strip_heredoc +
+ +
+ $ + + 0.0 +
+
+ HTML + + actual = @vertical_builder.text_field :name, bootstrap_form: {prepend: "$", append: "0.0"} + + expect(actual).to match_html(expected) + end + + it "supports button in input group" do + expected = <<~HTML.strip_heredoc +
+ +
+ + +
+
+ HTML + + actual = @vertical_builder.text_field :name, bootstrap_form: {append: (button_tag("Go", type: :submit, class: "btn btn-secondary"))} + + expect(actual).to match_html(expected) + end + + it "supports multiple addons in input group" do + expected = <<~HTML.strip_heredoc +
+ +
+ $ + Rs + + 0.0 +
+
+ HTML + + actual = @vertical_builder.text_field :name, bootstrap_form: {prepend: ["$", "Rs"], append: "0.0"} + + expect(actual).to match_html(expected) + end + + it "supports input group with floating labels" do + expected = <<~HTML.strip_heredoc +
+
+ $ +
+ + +
+ 0.0 +
+
+ HTML + + actual = @vertical_builder.text_field :name, bootstrap_form: {prepend: "$", append: "0.0", floating: true} + + expect(actual).to match_html(expected) + end + + it "changes size of the field" do + expected = <<~HTML.strip_heredoc +
+ + +
+ HTML + + actual = @vertical_builder.text_field :name, bootstrap_form: {size: :sm} + + expect(actual).to match_html(expected) + end + end +end diff --git a/spec/rails_bootstrap_form_spec.rb b/spec/rails_bootstrap_form_spec.rb index dd712e4..a7fadbc 100644 --- a/spec/rails_bootstrap_form_spec.rb +++ b/spec/rails_bootstrap_form_spec.rb @@ -6,7 +6,7 @@ RSpec.describe RailsBootstrapForm do it "has a valid version number" do - expect(RailsBootstrapForm::VERSION).to eq("0.6.0") + expect(RailsBootstrapForm::VERSION).to eq("0.6.1") end it "has a valid rails version number" do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9522ded..5c4320d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -7,6 +7,10 @@ require_relative "../demo/config/environment" require "simplecov" +# Requires supporting files with custom matchers and macros, etc, +# in ./support/ and its subdirectories. +Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |file| require file } + def spec_root Pathname.new(File.expand_path(__dir__)) end @@ -37,6 +41,27 @@ def test_directory_path c.syntax = :expect end + # This setting enables warnings. It's recommended, but in some cases may + # be too noisy due to issues in dependencies. + # config.warnings = true + + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + config.profile_examples = 10 + + config.include ActionView::Helpers::FormHelper + config.include ActionView::Context if defined?(ActionView::Context) + config.include RailsBootstrapForm::ActionViewExtensions::BootstrapFormHelper + config.include Rails.application.routes.url_helpers + config.include ActionDispatch::Routing::PolymorphicRoutes + + config.before(:each) do + @user = ::User.new + @vertical_builder = RailsBootstrapForm::BootstrapFormBuilder.new(:user, @user, self, {}) + @horizontal_builder = RailsBootstrapForm::BootstrapFormBuilder.new(:user, @user, self, bootstrap_form: {layout: :horizontal}) + end + config.before(:suite) do FileUtils.mkdir_p(test_directory_path) end diff --git a/spec/support/match_html_matcher.rb b/spec/support/match_html_matcher.rb new file mode 100644 index 0000000..18e56a1 --- /dev/null +++ b/spec/support/match_html_matcher.rb @@ -0,0 +1,25 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +require "nokogiri" +require "compare-xml" + +RSpec::Matchers.define :match_html do |expected_html, **options| + match do |actual_html| + expected_doc = Nokogiri::HTML5.fragment(expected_html) + actual_doc = Nokogiri::HTML5.fragment(actual_html) + + # Options are documented here: https://github.com/vkononov/compare-xml + default_options = { + collapse_whitespace: true, + ignore_attr_order: true, + ignore_comments: true, + } + + options = default_options.merge(options).merge(verbose: true) + + diff = CompareXML.equivalent?(expected_doc, actual_doc, **options) + diff.blank? + end +end diff --git a/spec/support/simplecov.rb b/spec/support/simplecov.rb new file mode 100644 index 0000000..4b31ccb --- /dev/null +++ b/spec/support/simplecov.rb @@ -0,0 +1,10 @@ +# -*- encoding: utf-8 -*- +# -*- frozen_string_literal: true -*- +# -*- warn_indent: true -*- + +SimpleCov.start "rails" do + add_filter "spec/" + add_filter ".github/" + add_filter "lib/generators/templates/" + add_filter "lib/rails_bootstrap_form/version" +end