-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Single File Rails Test App #14
Comments
I tested mine using a fake model that didn't require a database connection: class ArrayType < ActiveModel::Type::Value
def cast(value)
# Ensure it's always an array
Array(value.reject!(&:empty?))
end
end
class FakeModel
include ActiveModel::Model
include ActiveModel::Attributes
include ActiveRecord::Reflection::ClassMethods
# Define attributes with various data types
attribute :name, :string # String attribute
attribute :email, :string # String attribute
attribute :website_url, :string # String attribute
attribute :telephone_number, :string # String attribute
attribute :search_term, :string # String attribute
attribute :home_on_the_range, :string # String attribute
attribute :views_count, :integer # Integer attribute
attribute :description, :string # Text attribute
attribute :week_what_now, :string # Text attribute
attribute :month_what_now, :string # Text attribute
attribute :grouped_color, :string # Text attribute
attribute :published_on, :date # DateTime attribute
attribute :published_at, :datetime # DateTime attribute
attribute :local_timestamp, :datetime # DateTime attribute
attribute :password_confirmation, :string # DateTime attribute
attribute :hex_color, :string # DateTime attribute
attribute :current_time, :time
attribute :is_fast, :boolean # Boolean attribute
attribute :is_flashy, :boolean # Boolean attribute
attribute :color, :string # Text attribute
attribute :shape, :string
attribute :colors, ArrayType.new
attribute :sizes, ArrayType.new
attribute :multiple_shape, ArrayType.new
attribute :file, :string # String attribute for file (normally you'd use something like ActiveStorage for real files)
# Simulate associations
ASSOCIATIONS = {
comments: {type: :has_many, class_name: "Comment"},
author: {type: :belongs_to, class_name: "User"}
}.freeze
# Custom reflection class to simulate ActiveRecord::Reflection::AssociationReflection
class AssociationReflection
attr_reader :name, :macro, :class_name
def initialize(name, macro, class_name)
@name = name
@macro = macro
@class_name = class_name
end
end
# Method to simulate ActiveRecord's reflect_on_association
def self.reflect_on_association(association_name)
association = ASSOCIATIONS[association_name]
return nil unless association
AssociationReflection.new(association_name, association[:type], association[:class_name])
end
# You can add validations if needed
validates :name, presence: true
validates :week_what_now, presence: true
validates :month_what_now, presence: true
validates :description, presence: true
validates :views_count, numericality: {only_integer: true}
validates :website_url, presence: true
validates :telephone_number, presence: true
validates :home_on_the_range, inclusion: {in: ["25"], message: "must be '25'"}
validates :email, presence: true
validates :is_fast, inclusion: {in: [true], message: "must be 'Fast'"}
validates :is_flashy, inclusion: {in: [true], message: "must be 'Flashy'"}
validates :shape, inclusion: {in: ["triangle"], message: "must be 'Triangle'"}
validates :grouped_color, inclusion: {in: ["Blue"], message: "must be 'Blue'"}
validates :color, inclusion: {in: ["blue"], message: "must be 'Blue'"}
validates :file, presence: true
validates :password_confirmation, presence: true
validates :search_term, presence: true
validates :local_timestamp, presence: true
validates :hex_color, inclusion: {in: ["#ff0000"], message: "must be '#ff0000'"}
validate :must_include_blue
validate :must_include_large
validate :must_include_triangle
validate :date_stuff_is_always_invalid
private
def date_stuff_is_always_invalid
errors.add(:published_on, "is invalid")
errors.add(:published_at, "is invalid")
errors.add(:current_time, "is invalid")
end
def must_include_blue
errors.add(:colors, "must include 'Blue'") unless colors.include?("blue")
end
def must_include_large
errors.add(:sizes, "must include 'Large'") unless sizes.include?("large")
end
def must_include_triangle
errors.add(:multiple_shape, "must include 'Triangle'") unless multiple_shape.include?("triangle")
end
end This in my routes file: resources :fake_models A controller. Note the ability to change the options so that I was able to see what the form looked like with different sizes/colors/labels/hints etc. The one thing I forgot to do was include some kind of option to disable the inputs. It would be good to know what that looks like, and make sure it passes all the way through: class FakeModelsController < ApplicationController
before_action :set_options
def new
@fake_model = FakeModel.new
end
def create
@fake_model = FakeModel.new(fake_model_params)
if @fake_model.valid?
redirect_to root_path
else
render :new, status: :unprocessable_entity
end
end
private
def set_options
@color = "accent"
@size = "lg"
@hint = (false) ? "This is a hint!" : nil
@label = (true) ? nil : false
end
def fake_model_params
params.fetch(:fake_model, {}).permit(
:name,
:description,
:is_fast, :is_furious,
:is_flashy, :is_fun,
:color,
:shape,
:email,
:website_url,
:telephone_number,
:hex_color,
:password_confirmation,
:search_term,
:week_what_now,
:month_what_now,
:local_timestamp,
:home_on_the_range,
:grouped_color,
:views_count,
colors: [],
sizes: [],
multiple_shape: []
# We don't test this because it's hard to get a non-rails model
# to quack like a date/time object and accept the (1i) style params
# :current_time,
# :published_on,
# :published_at,
)
end
end And this view: .container
%h1.text-4xl.font-black.tracking-tighter
DaisyUI Test Form
= form_with model: @fake_model, html: {novalidate: true} do |f|
%h3.text-2xl.font-black.tracking-tighter.my-6.text-base-300 Checkbox
.my-3= f.input :is_fast, as: :boolean, label: @label, hint: @hint, input_html: {class: "checkbox-#{@color} checkbox-#{@size}"}
%h3.text-2xl.font-black.tracking-tighter.my-6.text-base-300 Checkboxes
.my-3= f.input :colors, as: :check_boxes, label: @label, hint: @hint, collection: ["Red","Green","Blue"], value_method: :downcase, text_method: :to_s, input_html: {class: "checkbox-#{@color} checkbox-#{@size}"}
%h3.text-2xl.font-black.tracking-tighter.my-6.text-base-300 File Input
.my-3= f.input :file, as: :file, label: @label, hint: @hint, input_html: {class: "file-input-#{@color} file-input-#{@size}"}
%h3.text-2xl.font-black.tracking-tighter.my-6.text-base-300 Radio
.my-3= f.input :color, as: :radio_buttons, label: @label, hint: @hint, collection: ["Red","Green","Blue"], value_method: :downcase, text_method: :to_s, input_html: {class: "radio-#{@color}"}
%h3.text-2xl.font-black.tracking-tighter.my-6.text-base-300 Range
.my-3= f.input :home_on_the_range, as: :range, label: @label, hint: @hint, input_html: {class: "range-#{@color} range-#{@size}", min: 0, max: 100, step: 5}, measure: 4
-# %h3.text-2xl.font-black.tracking-tighter.my-6.text-base-300 Rating
-# %p Not going to implement
%h3.text-2xl.font-black.tracking-tighter.my-6.text-base-300 Select
.my-3= f.input :shape, as: :select, label: @label, hint: @hint, collection: ["Circle","Square","Triangle"], value_method: :downcase, text_method: :to_s, input_html: {class: "select-#{@color} select-#{@size}"}
.my-3= f.input :multiple_shape, as: :select, label: @label, hint: @hint, collection: ["Circle","Square","Triangle"], multiple: true, value_method: :downcase, text_method: :to_s, input_html: {class: "select-#{@color} select-#{@size}"}
.my-3= f.input :grouped_color, as: :grouped_select, label: @label, hint: @hint, collection: { Primary: ["Red","Yellow","Blue"], Secondary: ["Green","Purple","Orange"]}, value_method: :downcase, text_method: :to_s, input_html: {class: "select-#{@color} select-#{@size}"}
%h3.text-2xl.font-black.tracking-tighter.my-6.text-base-300 Text Input
.my-3= f.input :name, label: @label, hint: @hint, input_html: {class: "input-#{@color} input-#{@size}"}
.my-3= f.input :email, as: :email, label: @label, hint: @hint, input_html: {class: "input-#{@color} input-#{@size}"}
.my-3= f.input :views_count, as: :integer, label: @label, hint: @hint, input_html: {class: "input-#{@color} input-#{@size}"}
.my-3= f.input :website_url, as: :url, label: @label, hint: @hint, input_html: {class: "input-#{@color} input-#{@size}"}
.my-3= f.input :telephone_number, as: :telephone, label: @label, hint: @hint, input_html: {class: "input-#{@color} input-#{@size}"}
.my-3= f.input :password_confirmation, as: :password, label: @label, hint: @hint, input_html: {class: "input-#{@color} input-#{@size}"}
.my-3= f.input :search_term, as: :search, label: @label, hint: @hint, input_html: {class: "input-#{@color} input-#{@size}"}
%h3.text-2xl.font-black.tracking-tighter.my-6.text-base-300 Color
.my-3= f.input :hex_color, as: :color, label: @label, hint: @hint, input_html: {class: "input-#{@color} input-#{@size}"}
%h3.text-2xl.font-black.tracking-tighter.my-6.text-base-300 Date/Time Inputs
.my-3= f.input :published_on, as: :date, label: @label, hint: @hint, input_html: {class: "select-#{@color} select-#{@size}"}
.my-3= f.input :published_at, as: :datetime, label: @label, hint: @hint, input_html: {class: "select-#{@color} select-#{@size}"}
.my-3= f.input :current_time, as: :time, label: @label, hint: @hint, input_html: {class: "select-#{@color} select-#{@size}"}
.my-3= f.input :week_what_now, as: :week, label: @label, hint: @hint, input_html: {class: "select-#{@color} select-#{@size}"}
.my-3= f.input :month_what_now, as: :month, label: @label, hint: @hint, input_html: {class: "select-#{@color} select-#{@size}"}
.my-3= f.input :local_timestamp, as: :datetime_local, label: @label, hint: @hint, input_html: {class: "input-#{@color} input-#{@size}"}
%h3.text-2xl.font-black.tracking-tighter.my-6.text-base-300 Textarea
.my-3= f.input :description, as: :text, label: @label, hint: @hint, input_html: {class: "textarea-#{@color} textarea-#{@size}"}
%h3.text-2xl.font-black.tracking-tighter.my-6.text-base-300 Toggle
.my-3= f.input :is_flashy, as: :toggle, label: @label, hint: @hint, input_html: {class: "toggle-#{@color} toggle-#{@size}"}
%h3.text-2xl.font-black.tracking-tighter.my-6.text-base-300 Toggles
.my-3= f.input :sizes, as: :toggles, label: @label, hint: @hint, collection: ["Small","Medium","Large"], value_method: :downcase, text_method: :to_s, input_html: {class: "toggle-#{@color} toggle-#{@size}"}
.my-3= f.submit class: "btn btn-primary"
%div
.file-input-accent.file-input-info.file-input-lg.file-input-sm.file-input-xs
.select-accent.select-info.select-lg.select-sm.select-xs
.checkbox-accent.checkbox-info.checkbox-lg.checkbox-sm.checkbox-xs
.radio-accent.radio-info.radio-lg.radio-sm.radio-xs
.input-accent.input-info.input-lg.input-sm.input-xs
.textarea-accent.textarea-info.textarea-lg.textarea-sm.textarea-xs
.toggle-accent.toggle-info.toggle-lg.toggle-sm.toggle-xs
.range.range-accent.range-info.range-lg.range-sm.range-xs Note the pile of CSS classes I threw in the last div there so that TailwindCSS watch would pick them up and include them in the stylesheet. |
Starting a very basic Single file rails app. I'm excited because the in memory sqlite database means we can do a real record/model setup here. # frozen_string_literal: true
require 'bundler/inline'
gemfile(true) do
source 'https://rubygems.org'
gem 'rails', '~> 8.0'
gem 'sqlite3'
gem "rackup"
gem "puma"
end
require 'rails/all'
database = ':memory:'
ENV['DATABASE_URL'] = "sqlite3:#{database}"
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: database)
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
create_table :posts, force: true do |t|
end
create_table :comments, force: true do |t|
t.integer :post_id
end
end
class App < Rails::Application
config.root = __dir__
config.consider_all_requests_local = true
config.secret_key_base = 'i_am_a_secret'
config.active_storage.service_configurations = { 'local' => { 'service' => 'Disk', 'root' => './storage' } }
routes.append do
root to: 'welcome#index'
end
end
class WelcomeController < ActionController::Base
def index
render inline: 'Hi!'
end
end
App.initialize!
Rackup::Server.start(app: App, Port: 3000) |
While working on #12 I was able to (easily) test the changes in an existing app.
However, it would be nice if it was super easy to work directly on the repo instead of copy-n-pasting back into this repo.
@willtcarey suggested a Single File Rails App, and that sounds cool!
The text was updated successfully, but these errors were encountered: