20 changed files with 659 additions and 1 deletions
-
1Gemfile
-
4Gemfile.lock
-
2Rakefile
-
289app/assets/stylesheets/formtastic.css
-
59app/controllers/posts_controller.rb
-
2app/helpers/posts_helper.rb
-
2app/models/post.rb
-
5app/views/posts/_form.html.erb
-
2app/views/posts/_post.html.erb
-
10app/views/posts/edit.html.erb
-
43app/views/posts/index.html.erb
-
9app/views/posts/new.html.erb
-
15app/views/posts/show.html.erb
-
118config/initializers/formtastic.rb
-
1config/routes.rb
-
11db/migrate/20260303141001_create_posts.rb
-
21db/schema.rb
-
48test/controllers/posts_controller_test.rb
-
11test/fixtures/posts.yml
-
7test/models/post_test.rb
@ -1,6 +1,6 @@ |
|||||
# Add your own tasks in files placed in lib/tasks ending in .rake, |
# Add your own tasks in files placed in lib/tasks ending in .rake, |
||||
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. |
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. |
||||
|
|
||||
require_relative "config/application" |
|
||||
|
require_relative 'config/application' |
||||
|
|
||||
Rails.application.load_tasks |
Rails.application.load_tasks |
||||
@ -0,0 +1,289 @@ |
|||||
|
/* ------------------------------------------------------------------------------------------------- |
||||
|
|
||||
|
It's *strongly* suggested that you don't modify this file. Instead, load a new stylesheet after |
||||
|
this one in your layouts (eg formtastic_changes.css) and override the styles to suit your needs. |
||||
|
This will allow you to update formtastic.css with new releases without clobbering your own changes. |
||||
|
|
||||
|
This stylesheet forms part of the Formtastic Rails gem |
||||
|
(c) Justin French |
||||
|
|
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
|
||||
|
/* NORMALIZE AND RESET - obviously inspired by Yahoo's reset.css, but scoped to just .formtastic |
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
.formtastic, |
||||
|
.formtastic ul, |
||||
|
.formtastic ol, |
||||
|
.formtastic li, |
||||
|
.formtastic fieldset, |
||||
|
.formtastic legend, |
||||
|
.formtastic input, |
||||
|
.formtastic button, |
||||
|
.formtastic textarea, |
||||
|
.formtastic select, |
||||
|
.formtastic p { |
||||
|
margin:0; |
||||
|
padding:0; |
||||
|
} |
||||
|
|
||||
|
.formtastic fieldset { |
||||
|
border:0; |
||||
|
} |
||||
|
|
||||
|
.formtastic em, |
||||
|
.formtastic strong { |
||||
|
font-style:normal; |
||||
|
font-weight:normal; |
||||
|
} |
||||
|
|
||||
|
.formtastic ol, |
||||
|
.formtastic ul { |
||||
|
list-style:none; |
||||
|
} |
||||
|
|
||||
|
.formtastic abbr, |
||||
|
.formtastic acronym { |
||||
|
border:0; |
||||
|
font-variant:normal; |
||||
|
} |
||||
|
|
||||
|
.formtastic input, |
||||
|
.formtastic button, |
||||
|
.formtastic textarea { |
||||
|
font-family:sans-serif; |
||||
|
font-size:inherit; |
||||
|
font-weight:inherit; |
||||
|
} |
||||
|
|
||||
|
.formtastic input, |
||||
|
.formtastic textarea, |
||||
|
.formtastic select { |
||||
|
font-size:100%; |
||||
|
} |
||||
|
|
||||
|
.formtastic legend { |
||||
|
white-space:normal; |
||||
|
color:#000; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* SEMANTIC ERRORS |
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
.formtastic .errors { |
||||
|
color:#cc0000; |
||||
|
margin:0.5em 0 1.5em 25%; |
||||
|
list-style:square; |
||||
|
} |
||||
|
|
||||
|
.formtastic .errors li { |
||||
|
padding:0; |
||||
|
border:none; |
||||
|
display:list-item; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* BUTTONS & ACTIONS |
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
.formtastic .buttons, |
||||
|
.formtastic .actions { |
||||
|
overflow:hidden; /* clear containing floats */ |
||||
|
padding-left:25%; |
||||
|
} |
||||
|
|
||||
|
.formtastic .button, |
||||
|
.formtastic .action { |
||||
|
float:left; |
||||
|
padding-right:0.5em; |
||||
|
} |
||||
|
|
||||
|
.formtastic .button_action button { |
||||
|
padding:3px 8px; |
||||
|
} |
||||
|
|
||||
|
.formtastic .link_action a { |
||||
|
display:block; |
||||
|
padding:3px 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* INPUTS |
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
.formtastic .inputs { |
||||
|
overflow:hidden; /* clear containing floats */ |
||||
|
} |
||||
|
|
||||
|
.formtastic .input { |
||||
|
overflow:hidden; /* clear containing floats */ |
||||
|
padding:0.5em 0; /* padding and negative margin juggling is for Firefox */ |
||||
|
margin-top:-0.5em; |
||||
|
margin-bottom:1em; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* LEFT ALIGNED LABELS |
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
.formtastic .input .label { |
||||
|
display:block; |
||||
|
width:25%; |
||||
|
float:left; |
||||
|
padding-top:.2em; |
||||
|
} |
||||
|
|
||||
|
.formtastic .fragments .label, |
||||
|
.formtastic .choices .label { |
||||
|
position:absolute; |
||||
|
width:95%; |
||||
|
left:0px; |
||||
|
} |
||||
|
|
||||
|
.formtastic .fragments .label label, |
||||
|
.formtastic .choices .label label { |
||||
|
position:absolute; |
||||
|
} |
||||
|
|
||||
|
/* NESTED FIELDSETS AND LEGENDS (radio, check boxes and date/time inputs use nested fieldsets) |
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
.formtastic .choices { |
||||
|
position:relative; |
||||
|
} |
||||
|
|
||||
|
.formtastic .choices-group { |
||||
|
float:left; |
||||
|
width:74%; |
||||
|
margin:0; |
||||
|
padding:0 0 0 25%; |
||||
|
} |
||||
|
|
||||
|
.formtastic .choice { |
||||
|
padding:0; |
||||
|
border:0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* INLINE HINTS |
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
.formtastic .input .inline-hints { |
||||
|
color:#666; |
||||
|
margin:0.5em 0 0 25%; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* INLINE ERRORS |
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
.formtastic .inline-errors { |
||||
|
color:#cc0000; |
||||
|
margin:0.5em 0 0 25%; |
||||
|
} |
||||
|
|
||||
|
.formtastic .errors { |
||||
|
color:#cc0000; |
||||
|
margin:0.5em 0 0 25%; |
||||
|
list-style:square; |
||||
|
} |
||||
|
|
||||
|
.formtastic .errors li { |
||||
|
padding:0; |
||||
|
border:none; |
||||
|
display:list-item; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* STRING, NUMERIC, PASSWORD, EMAIL, URL, PHONE, SEARCH (ETC) OVERRIDES |
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
.formtastic .stringish input { |
||||
|
width:72%; |
||||
|
} |
||||
|
|
||||
|
.formtastic .stringish input[size], |
||||
|
.formtastic .stringish input[max] { |
||||
|
width:auto; |
||||
|
max-width:72%; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* TEXTAREA OVERRIDES |
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
.formtastic .text textarea { |
||||
|
width:72%; |
||||
|
} |
||||
|
|
||||
|
.formtastic .text textarea[cols] { |
||||
|
width:auto; |
||||
|
max-width:72%; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* HIDDEN OVERRIDES |
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
.formtastic .hidden { |
||||
|
display:none; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* BOOLEAN LABELS |
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
.formtastic .boolean label { |
||||
|
margin-left:25%; |
||||
|
display:block; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* CHOICE GROUPS |
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
.formtastic .choices-group { |
||||
|
margin-bottom:-0.5em; |
||||
|
} |
||||
|
|
||||
|
.formtastic .choice { |
||||
|
margin:0.1em 0 0.5em 0; |
||||
|
} |
||||
|
|
||||
|
.formtastic .choice label { |
||||
|
float:none; |
||||
|
width:100%; |
||||
|
line-height:100%; |
||||
|
padding-top:0; |
||||
|
margin-bottom:0.6em; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* ADJUSTMENTS FOR INPUTS INSIDE LABELS (boolean input, radio input, check_boxes input) |
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
.formtastic .choice label input, |
||||
|
.formtastic .boolean label input { |
||||
|
margin:0 0.3em 0 0.1em; |
||||
|
line-height:100%; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* FRAGMENTED INPUTS (DATE/TIME/DATETIME) |
||||
|
--------------------------------------------------------------------------------------------------*/ |
||||
|
.formtastic .fragments { |
||||
|
position:relative; |
||||
|
} |
||||
|
|
||||
|
.formtastic .fragments-group { |
||||
|
float:left; |
||||
|
width:74%; |
||||
|
margin:0; |
||||
|
padding:0 0 0 25%; |
||||
|
} |
||||
|
|
||||
|
.formtastic .fragment { |
||||
|
float:left; |
||||
|
width:auto; |
||||
|
margin:0 .3em 0 0; |
||||
|
padding:0; |
||||
|
border:0; |
||||
|
} |
||||
|
|
||||
|
.formtastic .fragment label { |
||||
|
display:none; |
||||
|
} |
||||
|
|
||||
|
.formtastic .fragment label input { |
||||
|
display:inline; |
||||
|
margin:0; |
||||
|
padding:0; |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,59 @@ |
|||||
|
class PostsController < ApplicationController |
||||
|
before_action :set_post, only: %i[show edit update destroy] |
||||
|
|
||||
|
# GET /posts |
||||
|
def index |
||||
|
@posts = Post.all |
||||
|
end |
||||
|
|
||||
|
# GET /posts/1 |
||||
|
def show |
||||
|
end |
||||
|
|
||||
|
# GET /posts/new |
||||
|
def new |
||||
|
@post = Post.new |
||||
|
end |
||||
|
|
||||
|
# GET /posts/1/edit |
||||
|
def edit |
||||
|
end |
||||
|
|
||||
|
# POST /posts |
||||
|
def create |
||||
|
@post = Post.new(post_params) |
||||
|
|
||||
|
if @post.save |
||||
|
redirect_to @post, notice: 'Post was successfully created.' |
||||
|
else |
||||
|
render :new, status: :unprocessable_content |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
# PATCH/PUT /posts/1 |
||||
|
def update |
||||
|
if @post.update(post_params) |
||||
|
redirect_to @post, notice: 'Post was successfully updated.', status: :see_other |
||||
|
else |
||||
|
render :edit, status: :unprocessable_content |
||||
|
end |
||||
|
end |
||||
|
|
||||
|
# DELETE /posts/1 |
||||
|
def destroy |
||||
|
@post.destroy! |
||||
|
redirect_to posts_path, notice: 'Post was successfully destroyed.', status: :see_other |
||||
|
end |
||||
|
|
||||
|
private |
||||
|
|
||||
|
# Use callbacks to share common setup or constraints between actions. |
||||
|
def set_post |
||||
|
@post = Post.find(params.expect(:id)) |
||||
|
end |
||||
|
|
||||
|
# Only allow a list of trusted parameters through. |
||||
|
def post_params |
||||
|
params.require(:post).permit(:title, :quantity, :content) |
||||
|
end |
||||
|
end |
||||
@ -0,0 +1,2 @@ |
|||||
|
module PostsHelper |
||||
|
end |
||||
@ -0,0 +1,2 @@ |
|||||
|
class Post < ApplicationRecord |
||||
|
end |
||||
@ -0,0 +1,5 @@ |
|||||
|
<%= semantic_form_for @post do |f| %> |
||||
|
<%= f.inputs %> |
||||
|
<%= f.semantic_errors :state %> |
||||
|
<%= f.actions %> |
||||
|
<% end %> |
||||
@ -0,0 +1,2 @@ |
|||||
|
<div id="<%= dom_id post %>" class="w-full sm:w-auto my-5 space-y-5"> |
||||
|
</div> |
||||
@ -0,0 +1,10 @@ |
|||||
|
<% content_for :title, "Editing post" %> |
||||
|
|
||||
|
<div class="md:w-2/3 w-full"> |
||||
|
<h1 class="font-bold text-4xl">Editing post</h1> |
||||
|
|
||||
|
<%= render "form", post: @post %> |
||||
|
|
||||
|
<%= link_to "Show this post", @post, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> |
||||
|
<%= link_to "Back to posts", posts_path, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> |
||||
|
</div> |
||||
@ -0,0 +1,43 @@ |
|||||
|
<% content_for :title, "Posts" %> |
||||
|
|
||||
|
<div class="w-full"> |
||||
|
<% if notice.present? %> |
||||
|
<p |
||||
|
class=" |
||||
|
py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-md |
||||
|
inline-block |
||||
|
" |
||||
|
id="notice" |
||||
|
> |
||||
|
<%= notice %> |
||||
|
</p> |
||||
|
<% end %> |
||||
|
|
||||
|
<div class="flex justify-between items-center"> |
||||
|
<h1 class="font-bold text-4xl">Posts</h1> |
||||
|
<%= link_to "New post", new_post_path, class: "rounded-md px-3.5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white block font-medium" %> |
||||
|
</div> |
||||
|
|
||||
|
<div id="posts" class="min-w-full divide-y divide-gray-200 space-y-5"> |
||||
|
<% if @posts.any? %> |
||||
|
<% @posts.each do |post| %> |
||||
|
<div |
||||
|
class=" |
||||
|
flex flex-col sm:flex-row justify-between items-center pb-5 |
||||
|
sm:pb-0 |
||||
|
" |
||||
|
> |
||||
|
<%= render post %> |
||||
|
|
||||
|
<div class="w-full sm:w-auto flex flex-col sm:flex-row space-x-2 space-y-2"> |
||||
|
<%= link_to "Show", post, class: "btn btn-primary" %> |
||||
|
<%= link_to "Edit", edit_post_path(post), class: "btn btn-secondary" %> |
||||
|
<%= button_to "Destroy", post, method: :delete, class: "btn btn-accent", data: { turbo_confirm: "Are you sure?" } %> |
||||
|
</div> |
||||
|
</div> |
||||
|
<% end %> |
||||
|
<% else %> |
||||
|
<p class="text-center my-10">No posts found.</p> |
||||
|
<% end %> |
||||
|
</div> |
||||
|
</div> |
||||
@ -0,0 +1,9 @@ |
|||||
|
<% content_for :title, "New post" %> |
||||
|
|
||||
|
<div class="md:w-2/3 w-full"> |
||||
|
<h1 class="font-bold text-4xl">New post</h1> |
||||
|
|
||||
|
<%= render "form", post: @post %> |
||||
|
|
||||
|
<%= link_to "Back to posts", posts_path, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> |
||||
|
</div> |
||||
@ -0,0 +1,15 @@ |
|||||
|
<% content_for :title, "Showing post" %> |
||||
|
|
||||
|
<div class="md:w-2/3 w-full"> |
||||
|
<% if notice.present? %> |
||||
|
<p class="py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-md inline-block" id="notice"><%= notice %></p> |
||||
|
<% end %> |
||||
|
|
||||
|
<h1 class="font-bold text-4xl">Showing post</h1> |
||||
|
|
||||
|
<%= render @post %> |
||||
|
|
||||
|
<%= link_to "Edit this post", edit_post_path(@post), class: "w-full sm:w-auto text-center rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> |
||||
|
<%= link_to "Back to posts", posts_path, class: "w-full sm:w-auto text-center mt-2 sm:mt-0 sm:ml-2 rounded-md px-3.5 py-2.5 bg-gray-100 hover:bg-gray-50 inline-block font-medium" %> |
||||
|
<%= button_to "Destroy this post", @post, method: :delete, form_class: "sm:inline-block mt-2 sm:mt-0 sm:ml-2", class: "w-full rounded-md px-3.5 py-2.5 text-white bg-red-600 hover:bg-red-500 font-medium cursor-pointer", data: { turbo_confirm: "Are you sure?" } %> |
||||
|
</div> |
||||
@ -0,0 +1,118 @@ |
|||||
|
# frozen_string_literal: true |
||||
|
|
||||
|
# Set the default text field size when input is a string. Default is nil. |
||||
|
# Formtastic::FormBuilder.default_text_field_size = 50 |
||||
|
|
||||
|
# Set the default text area height when input is a text. Default is 20. |
||||
|
# Formtastic::FormBuilder.default_text_area_height = 5 |
||||
|
|
||||
|
# Set the default text area width when input is a text. Default is nil. |
||||
|
# Formtastic::FormBuilder.default_text_area_width = 50 |
||||
|
|
||||
|
# Should all fields be considered "required" by default? |
||||
|
# Defaults to true. |
||||
|
# Formtastic::FormBuilder.all_fields_required_by_default = true |
||||
|
|
||||
|
# Should select fields have a blank option/prompt by default? |
||||
|
# Defaults to true. |
||||
|
# Formtastic::FormBuilder.include_blank_for_select_by_default = true |
||||
|
|
||||
|
# Set the string that will be appended to the labels/fieldsets which are required. |
||||
|
# It accepts string or procs and the default is a localized version of |
||||
|
# '<abbr title="required">*</abbr>'. In other words, if you configure formtastic.required |
||||
|
# in your locale, it will replace the abbr title properly. But if you don't want to use |
||||
|
# abbr tag, you can simply give a string as below. |
||||
|
# Formtastic::FormBuilder.required_string = "(required)" |
||||
|
|
||||
|
# Set the string that will be appended to the labels/fieldsets which are optional. |
||||
|
# Defaults to an empty string ("") and also accepts procs (see required_string above). |
||||
|
# Formtastic::FormBuilder.optional_string = "(optional)" |
||||
|
|
||||
|
# Set the way inline errors will be displayed. |
||||
|
# Defaults to :sentence, valid options are :sentence, :list, :first and :none |
||||
|
# Formtastic::FormBuilder.inline_errors = :sentence |
||||
|
# Formtastic uses the following classes as default for hints, inline_errors and error list |
||||
|
|
||||
|
# If you override the class here, please ensure to override it in your stylesheets as well. |
||||
|
# Formtastic::FormBuilder.default_hint_class = "inline-hints" |
||||
|
# Formtastic::FormBuilder.default_inline_error_class = "inline-errors" |
||||
|
# Formtastic::FormBuilder.default_error_list_class = "errors" |
||||
|
|
||||
|
# Set the method to call on label text to transform or format it for human-friendly |
||||
|
# reading when formtastic is used without object. Defaults to :humanize. |
||||
|
# Formtastic::FormBuilder.label_str_method = :humanize |
||||
|
|
||||
|
# Set the array of methods to try calling on parent objects in :select and :radio inputs |
||||
|
# for the text inside each @<option>@ tag or alongside each radio @<input>@. The first method |
||||
|
# that is found on the object will be used. |
||||
|
# Defaults to ["to_label", "display_name", "full_name", "name", "title", "username", "login", "value", "to_s"] |
||||
|
# Formtastic::FormBuilder.collection_label_methods = [ |
||||
|
# "to_label", "display_name", "full_name", "name", "title", "username", "login", "value", "to_s"] |
||||
|
|
||||
|
# Specifies if labels/hints for input fields automatically be looked up using I18n. |
||||
|
# Default value: true. Overridden for specific fields by setting value to true, |
||||
|
# i.e. :label => true, or :hint => true (or opposite depending on initialized value) |
||||
|
# Formtastic::FormBuilder.i18n_lookups_by_default = false |
||||
|
|
||||
|
# Specifies if I18n lookups of the default I18n Localizer should be cached to improve performance. |
||||
|
# Defaults to true. |
||||
|
# Formtastic::FormBuilder.i18n_cache_lookups = false |
||||
|
|
||||
|
# Specifies the class to use for localization lookups. You can create your own |
||||
|
# class and use it instead by subclassing Formtastic::Localizer (which is the default). |
||||
|
# Formtastic::FormBuilder.i18n_localizer = MyOwnLocalizer |
||||
|
|
||||
|
# You can add custom inputs or override parts of Formtastic by subclassing Formtastic::FormBuilder and |
||||
|
# specifying that class here. Defaults to Formtastic::FormBuilder. |
||||
|
# Formtastic::Helpers::FormHelper.builder = MyCustomBuilder |
||||
|
|
||||
|
# All formtastic forms have a class that indicates that they are just that. You |
||||
|
# can change it to any class you want. |
||||
|
# Formtastic::Helpers::FormHelper.default_form_class = 'formtastic' |
||||
|
|
||||
|
# Formtastic will infer a class name from the model, array, string or symbol you pass to the |
||||
|
# form builder. You can customize the way that class is presented by overriding |
||||
|
# this proc. |
||||
|
# Formtastic::Helpers::FormHelper.default_form_model_class_proc = proc { |model_class_name| model_class_name } |
||||
|
|
||||
|
# Allows to set a custom field_error_proc wrapper. By default this wrapper |
||||
|
# is disabled since `formtastic` already adds an error class to the LI tag |
||||
|
# containing the input. |
||||
|
# Formtastic::Helpers::FormHelper.formtastic_field_error_proc = proc { |html_tag, instance_tag| html_tag } |
||||
|
|
||||
|
# You can opt-in to Formtastic's use of the HTML5 `required` attribute on `<input>`, `<select>` |
||||
|
# and `<textarea>` tags by setting this to true (defaults to false). |
||||
|
# Formtastic::FormBuilder.use_required_attribute = false |
||||
|
|
||||
|
# You can opt-in to new HTML5 browser validations (for things like email and url inputs) by setting |
||||
|
# this to true. Doing so will omit the `novalidate` attribute from the `<form>` tag. |
||||
|
# See http://diveintohtml5.org/forms.html#validation for more info. |
||||
|
# Formtastic::FormBuilder.perform_browser_validations = true |
||||
|
|
||||
|
# By creating custom input class finder, you can change how input classes are looked up. |
||||
|
# For example you can make it to search for TextInputFilter instead of TextInput. |
||||
|
# See https://github.com/formtastic/formtastic/wiki/Custom-Class-Finders |
||||
|
# Formtastic::FormBuilder.input_class_finder = Formtastic::InputClassFinder |
||||
|
|
||||
|
# Define custom namespaces in which to look up your Input classes. Default is |
||||
|
# to look up in the global scope and in Formtastic::Inputs. |
||||
|
# Formtastic::FormBuilder.input_namespaces = [ ::Object, ::MyInputsModule, ::Formtastic::Inputs ] |
||||
|
|
||||
|
# By creating custom action class finder, you can change how action classes are looked up. |
||||
|
# For example you can make it to search for MyButtonAction instead of ButtonAction. |
||||
|
# See https://github.com/formtastic/formtastic/wiki/Custom-Class-Finders |
||||
|
# Formtastic::FormBuilder.action_class_finder = Formtastic::ActionClassFinder |
||||
|
|
||||
|
# Define custom namespaces in which to look up your Action classes. Default is |
||||
|
# to look up in the global scope and in Formtastic::Actions. |
||||
|
# Formtastic::FormBuilder.action_namespaces = [ ::Object, ::MyActionsModule, ::Formtastic::Actions ] |
||||
|
|
||||
|
# Which columns to skip when automatically rendering a form without any fields specified. |
||||
|
# Formtastic::FormBuilder.skipped_columns = [:created_at, :updated_at, :created_on, :updated_on, :lock_version, :version] |
||||
|
|
||||
|
# You can opt-in to accessibility features for the `semantic_errors` helper by setting |
||||
|
# this to true. Doing so will render the attributes in the error summary list |
||||
|
# as `<li> <a>` links to the inputs that have errors. the inline error sentence's id is added to |
||||
|
# the errored input's aria-describedby. This ensures that the errored input is read out with |
||||
|
# the inline error sentence's error explanation, aria-invalid is set to true for errored inputs |
||||
|
# Formtastic::FormBuilder.semantic_errors_link_to_inputs = true |
||||
@ -0,0 +1,11 @@ |
|||||
|
class CreatePosts < ActiveRecord::Migration[8.1] |
||||
|
def change |
||||
|
create_table :posts do |t| |
||||
|
t.string :title |
||||
|
t.integer :quantity |
||||
|
t.string :content |
||||
|
|
||||
|
t.timestamps |
||||
|
end |
||||
|
end |
||||
|
end |
||||
@ -0,0 +1,21 @@ |
|||||
|
# This file is auto-generated from the current state of the database. Instead |
||||
|
# of editing this file, please use the migrations feature of Active Record to |
||||
|
# incrementally modify your database, and then regenerate this schema definition. |
||||
|
# |
||||
|
# This file is the source Rails uses to define your schema when running `bin/rails |
||||
|
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to |
||||
|
# be faster and is potentially less error prone than running all of your |
||||
|
# migrations from scratch. Old migrations may fail to apply correctly if those |
||||
|
# migrations use external dependencies or application code. |
||||
|
# |
||||
|
# It's strongly recommended that you check this file into your version control system. |
||||
|
|
||||
|
ActiveRecord::Schema[8.1].define(version: 2026_03_03_141001) do |
||||
|
create_table "posts", force: :cascade do |t| |
||||
|
t.string "content" |
||||
|
t.datetime "created_at", null: false |
||||
|
t.integer "quantity" |
||||
|
t.string "title" |
||||
|
t.datetime "updated_at", null: false |
||||
|
end |
||||
|
end |
||||
@ -0,0 +1,48 @@ |
|||||
|
require "test_helper" |
||||
|
|
||||
|
class PostsControllerTest < ActionDispatch::IntegrationTest |
||||
|
setup do |
||||
|
@post = posts(:one) |
||||
|
end |
||||
|
|
||||
|
test "should get index" do |
||||
|
get posts_url |
||||
|
assert_response :success |
||||
|
end |
||||
|
|
||||
|
test "should get new" do |
||||
|
get new_post_url |
||||
|
assert_response :success |
||||
|
end |
||||
|
|
||||
|
test "should create post" do |
||||
|
assert_difference("Post.count") do |
||||
|
post posts_url, params: { post: {} } |
||||
|
end |
||||
|
|
||||
|
assert_redirected_to post_url(Post.last) |
||||
|
end |
||||
|
|
||||
|
test "should show post" do |
||||
|
get post_url(@post) |
||||
|
assert_response :success |
||||
|
end |
||||
|
|
||||
|
test "should get edit" do |
||||
|
get edit_post_url(@post) |
||||
|
assert_response :success |
||||
|
end |
||||
|
|
||||
|
test "should update post" do |
||||
|
patch post_url(@post), params: { post: {} } |
||||
|
assert_redirected_to post_url(@post) |
||||
|
end |
||||
|
|
||||
|
test "should destroy post" do |
||||
|
assert_difference("Post.count", -1) do |
||||
|
delete post_url(@post) |
||||
|
end |
||||
|
|
||||
|
assert_redirected_to posts_url |
||||
|
end |
||||
|
end |
||||
@ -0,0 +1,11 @@ |
|||||
|
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html |
||||
|
|
||||
|
one: |
||||
|
title: MyString |
||||
|
quantity: 1 |
||||
|
content: MyString |
||||
|
|
||||
|
two: |
||||
|
title: MyString |
||||
|
quantity: 1 |
||||
|
content: MyString |
||||
@ -0,0 +1,7 @@ |
|||||
|
require "test_helper" |
||||
|
|
||||
|
class PostTest < ActiveSupport::TestCase |
||||
|
# test "the truth" do |
||||
|
# assert true |
||||
|
# end |
||||
|
end |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue