From 4bffc715199658285a4299066e209d42c4c624ca Mon Sep 17 00:00:00 2001 From: Igor Kasyanchuk Date: Tue, 28 Aug 2018 12:22:00 -0700 Subject: [PATCH] show validation message --- Gemfile | 2 +- Gemfile.lock | 4 +- README.md | 14 +++++ docs/preview.png | Bin 0 -> 19021 bytes lib/active_storage_validations.rb | 7 ++- lib/active_storage_validations/version.rb | 2 +- test/dummy/.ruby-version | 1 - test/dummy/app/assets/javascripts/projects.js | 2 + .../dummy/app/assets/stylesheets/projects.css | 4 ++ .../app/controllers/projects_controller.rb | 58 ++++++++++++++++++ test/dummy/app/helpers/projects_helper.rb | 2 + test/dummy/app/models/project.rb | 19 ++++++ .../app/views/layouts/application.html.erb | 4 ++ test/dummy/app/views/projects/_form.html.erb | 32 ++++++++++ test/dummy/app/views/projects/edit.html.erb | 6 ++ test/dummy/app/views/projects/index.html.erb | 27 ++++++++ test/dummy/app/views/projects/new.html.erb | 5 ++ test/dummy/app/views/projects/show.html.erb | 19 ++++++ test/dummy/config/routes.rb | 1 + .../migrate/20180828190302_create_projects.rb | 9 +++ test/dummy/db/schema.rb | 8 ++- 21 files changed, 219 insertions(+), 7 deletions(-) create mode 100755 docs/preview.png delete mode 100644 test/dummy/.ruby-version create mode 100644 test/dummy/app/assets/javascripts/projects.js create mode 100644 test/dummy/app/assets/stylesheets/projects.css create mode 100755 test/dummy/app/controllers/projects_controller.rb create mode 100644 test/dummy/app/helpers/projects_helper.rb create mode 100755 test/dummy/app/models/project.rb mode change 100644 => 100755 test/dummy/app/views/layouts/application.html.erb create mode 100755 test/dummy/app/views/projects/_form.html.erb create mode 100644 test/dummy/app/views/projects/edit.html.erb create mode 100644 test/dummy/app/views/projects/index.html.erb create mode 100644 test/dummy/app/views/projects/new.html.erb create mode 100755 test/dummy/app/views/projects/show.html.erb create mode 100644 test/dummy/db/migrate/20180828190302_create_projects.rb diff --git a/Gemfile b/Gemfile index 7d52514..b64f4a7 100755 --- a/Gemfile +++ b/Gemfile @@ -14,6 +14,6 @@ gemspec # To use a debugger # gem 'byebug', group: [:development, :test] -group :test do +group :development, :test do gem 'pry' end diff --git a/Gemfile.lock b/Gemfile.lock index 0a46000..ddd3afc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - active_storage_validations (0.1) + active_storage_validations (0.3) rails (~> 5.2.0) GEM @@ -129,4 +129,4 @@ DEPENDENCIES sqlite3 BUNDLED WITH - 1.13.6 + 1.16.1 diff --git a/README.md b/README.md index 3fc708d..b1a767a 100755 --- a/README.md +++ b/README.md @@ -20,6 +20,20 @@ class User < ApplicationRecord end ``` +or + +```ruby +class Project < ApplicationRecord + has_one_attached :preview + has_one_attached :attachment + + validates :title, presence: true + + validates :preview, attached: true + validates :attachment, attached: true, content_type: { in: 'application/pdf', message: 'is not a PDF' } +end +``` + ## Installation Add this line to your application's Gemfile: diff --git a/docs/preview.png b/docs/preview.png new file mode 100755 index 0000000000000000000000000000000000000000..3e497b484353bb319009f39e3abe7a51afe8a299 GIT binary patch literal 19021 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 literal 0 HcmV?d00001 diff --git a/lib/active_storage_validations.rb b/lib/active_storage_validations.rb index f436498..33a8715 100755 --- a/lib/active_storage_validations.rb +++ b/lib/active_storage_validations.rb @@ -11,6 +11,11 @@ def validate_each(record, attribute, value) end class ContentTypeValidator < ActiveModel::EachValidator + + # def initialize(options) + # super(options) + # end + def validate_each(record, attribute, value) files = record.send(attribute) @@ -24,7 +29,7 @@ def validate_each(record, attribute, value) files.each do |file| unless content_type_valid?(file) - record.errors.add(attribute, :invalid) + record.errors.add(attribute, options[:message].presence || :invalid) return end end diff --git a/lib/active_storage_validations/version.rb b/lib/active_storage_validations/version.rb index aeee0fe..8d28e89 100755 --- a/lib/active_storage_validations/version.rb +++ b/lib/active_storage_validations/version.rb @@ -1,3 +1,3 @@ module ActiveStorageValidations - VERSION = '0.2' + VERSION = '0.3' end diff --git a/test/dummy/.ruby-version b/test/dummy/.ruby-version deleted file mode 100644 index 3dd96ce..0000000 --- a/test/dummy/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -ruby-2.3.1 \ No newline at end of file diff --git a/test/dummy/app/assets/javascripts/projects.js b/test/dummy/app/assets/javascripts/projects.js new file mode 100644 index 0000000..dee720f --- /dev/null +++ b/test/dummy/app/assets/javascripts/projects.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/test/dummy/app/assets/stylesheets/projects.css b/test/dummy/app/assets/stylesheets/projects.css new file mode 100644 index 0000000..afad32d --- /dev/null +++ b/test/dummy/app/assets/stylesheets/projects.css @@ -0,0 +1,4 @@ +/* + Place all the styles related to the matching controller here. + They will automatically be included in application.css. +*/ diff --git a/test/dummy/app/controllers/projects_controller.rb b/test/dummy/app/controllers/projects_controller.rb new file mode 100755 index 0000000..6d0be3c --- /dev/null +++ b/test/dummy/app/controllers/projects_controller.rb @@ -0,0 +1,58 @@ +class ProjectsController < ApplicationController + before_action :set_project, only: [:show, :edit, :update, :destroy] + + # GET /projects + def index + @projects = Project.all + end + + # GET /projects/1 + def show + end + + # GET /projects/new + def new + @project = Project.new + end + + # GET /projects/1/edit + def edit + end + + # POST /projects + def create + @project = Project.new(project_params) + + if @project.save + redirect_to @project, notice: 'Project was successfully created.' + else + render :new + end + end + + # PATCH/PUT /projects/1 + def update + if @project.update(project_params) + redirect_to @project, notice: 'Project was successfully updated.' + else + render :edit + end + end + + # DELETE /projects/1 + def destroy + @project.destroy + redirect_to projects_url, notice: 'Project was successfully destroyed.' + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_project + @project = Project.find(params[:id]) + end + + # Only allow a trusted parameter "white list" through. + def project_params + params.require(:project).permit! + end +end diff --git a/test/dummy/app/helpers/projects_helper.rb b/test/dummy/app/helpers/projects_helper.rb new file mode 100644 index 0000000..db5c5ce --- /dev/null +++ b/test/dummy/app/helpers/projects_helper.rb @@ -0,0 +1,2 @@ +module ProjectsHelper +end diff --git a/test/dummy/app/models/project.rb b/test/dummy/app/models/project.rb new file mode 100755 index 0000000..7e97870 --- /dev/null +++ b/test/dummy/app/models/project.rb @@ -0,0 +1,19 @@ +# == Schema Information +# +# Table name: projects +# +# id :integer not null, primary key +# title :string +# created_at :datetime not null +# updated_at :datetime not null +# + +class Project < ApplicationRecord + has_one_attached :preview + has_one_attached :attachment + + validates :title, presence: true + + validates :preview, attached: true + validates :attachment, attached: true, content_type: { in: 'application/pdf', message: 'is not a PDF' } +end diff --git a/test/dummy/app/views/layouts/application.html.erb b/test/dummy/app/views/layouts/application.html.erb old mode 100644 new mode 100755 index 6093a4c..d69e57d --- a/test/dummy/app/views/layouts/application.html.erb +++ b/test/dummy/app/views/layouts/application.html.erb @@ -10,6 +10,10 @@ +
    +
  • <%= link_to 'Users', users_path %>
  • +
  • <%= link_to 'Projects', projects_path %>
  • +
<%= yield %> diff --git a/test/dummy/app/views/projects/_form.html.erb b/test/dummy/app/views/projects/_form.html.erb new file mode 100755 index 0000000..5abe63f --- /dev/null +++ b/test/dummy/app/views/projects/_form.html.erb @@ -0,0 +1,32 @@ +<%= form_with(model: project, local: true) do |form| %> + <% if project.errors.any? %> +
+

<%= pluralize(project.errors.count, "error") %> prohibited this project from being saved:

+ +
    + <% project.errors.full_messages.each do |message| %> +
  • <%= message %>
  • + <% end %> +
+
+ <% end %> + +
+ <%= form.label :title %> + <%= form.text_field :title %> +
+ +
+ <%= form.label :preview %> + <%= form.file_field :preview %> +
+ +
+ <%= form.label :attachment %> + <%= form.file_field :attachment %> +
+ +
+ <%= form.submit %> +
+<% end %> diff --git a/test/dummy/app/views/projects/edit.html.erb b/test/dummy/app/views/projects/edit.html.erb new file mode 100644 index 0000000..6c4bfc6 --- /dev/null +++ b/test/dummy/app/views/projects/edit.html.erb @@ -0,0 +1,6 @@ +

Editing Project

+ +<%= render 'form', project: @project %> + +<%= link_to 'Show', @project %> | +<%= link_to 'Back', projects_path %> diff --git a/test/dummy/app/views/projects/index.html.erb b/test/dummy/app/views/projects/index.html.erb new file mode 100644 index 0000000..2259b29 --- /dev/null +++ b/test/dummy/app/views/projects/index.html.erb @@ -0,0 +1,27 @@ +

<%= notice %>

+ +

Projects

+ + + + + + + + + + + <% @projects.each do |project| %> + + + + + + + <% end %> + +
Title
<%= project.title %><%= link_to 'Show', project %><%= link_to 'Edit', edit_project_path(project) %><%= link_to 'Destroy', project, method: :delete, data: { confirm: 'Are you sure?' } %>
+ +
+ +<%= link_to 'New Project', new_project_path %> diff --git a/test/dummy/app/views/projects/new.html.erb b/test/dummy/app/views/projects/new.html.erb new file mode 100644 index 0000000..1133074 --- /dev/null +++ b/test/dummy/app/views/projects/new.html.erb @@ -0,0 +1,5 @@ +

New Project

+ +<%= render 'form', project: @project %> + +<%= link_to 'Back', projects_path %> diff --git a/test/dummy/app/views/projects/show.html.erb b/test/dummy/app/views/projects/show.html.erb new file mode 100755 index 0000000..fbd58ab --- /dev/null +++ b/test/dummy/app/views/projects/show.html.erb @@ -0,0 +1,19 @@ +

<%= notice %>

+ +

+ Title: + <%= @project.title %> +

+ +

+ Preview: + <%= link_to 'download', @project.preview %> +

+ +

+ Attachment: + <%= link_to 'download', @project.attachment %> +

+ +<%= link_to 'Edit', edit_project_path(@project) %> | +<%= link_to 'Back', projects_path %> diff --git a/test/dummy/config/routes.rb b/test/dummy/config/routes.rb index 34fca7a..15aca95 100755 --- a/test/dummy/config/routes.rb +++ b/test/dummy/config/routes.rb @@ -1,4 +1,5 @@ Rails.application.routes.draw do + resources :projects resources :users root 'users#index' end diff --git a/test/dummy/db/migrate/20180828190302_create_projects.rb b/test/dummy/db/migrate/20180828190302_create_projects.rb new file mode 100644 index 0000000..548fd76 --- /dev/null +++ b/test/dummy/db/migrate/20180828190302_create_projects.rb @@ -0,0 +1,9 @@ +class CreateProjects < ActiveRecord::Migration[5.2] + def change + create_table :projects do |t| + t.string :title + + t.timestamps + end + end +end diff --git a/test/dummy/db/schema.rb b/test/dummy/db/schema.rb index a740e07..7b2673c 100644 --- a/test/dummy/db/schema.rb +++ b/test/dummy/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2018_08_28_145143) do +ActiveRecord::Schema.define(version: 2018_08_28_190302) do create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false @@ -33,6 +33,12 @@ t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true end + create_table "projects", force: :cascade do |t| + t.string "title" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "users", force: :cascade do |t| t.string "name" t.datetime "created_at", null: false