Railsamples

Practical examples to master web forms in Rails

Other - HABTM Checkboxes

This example shows how to assign multiple tags to articles through checkboxes.

ENV["SECRET_KEY_BASE"] = "1212312313"
ENV["DATABASE_URL"] = "sqlite3:///#{__dir__}/database.sqlite"

require "bundler/inline"

gemfile do
  source "https://www.rubygems.org"
  gem "uni_rails", "0.4.1"
  gem "sqlite3", "~> 1.7"
  gem "byebug"
end

require "uni_rails"
require "sqlite3"
require "byebug"

#  ==== ROUTES ====

UniRails::App.routes.append do
  root "posts#index"
  resources :posts
end

#  ==== DB SCHEMA ====

ActiveRecord::Base.establish_connection
ActiveRecord::Schema.define do
  create_table :posts, force: :cascade do |t|
    t.string :title
    t.timestamps
  end

  create_table :tags, force: :cascade do |t|
    t.string :name
    t.timestamps
  end

  create_join_table :posts, :tags, force: true
end

#  ==== MODELS ====

class Post < ActiveRecord::Base
  has_and_belongs_to_many :tags

  validates :title, presence: true

  def tag_names
    tags.pluck(:name)
  end
end

class Tag < ActiveRecord::Base
  has_and_belongs_to_many :post
end

#  ==== SEEDS ====

%w[Help Learning Question News Tutorial Discussion].each do |tag_name|
  Tag.create(name: tag_name)
end

Post.create(title: 'A new Ruby gem')
Post.create(title: 'Hello Rails World')
Post.create(title: 'That neat Rails form trick')

#  ==== CONTROLLERS ====

class PostsController < ActionController::Base
  layout 'application'

  def index
    @posts = Post.includes(:tags).all
  end

  def new
    @post = Post.new
  end

  def create
    @post = Post.new(post_params)
    if @post.save
      redirect_to posts_path, notice: 'created successfully'
    else
      render :new
    end
  end

  def edit
    @post = Post.find(params[:id])
  end

  def update
    @post = Post.find(params[:id])
    if @post.update(post_params)
      redirect_to posts_path, notice: 'updated successfully'
    else
      render :edit
    end
  end

  def destroy
    Post.find(params[:id]).destroy
    redirect_to posts_path, notice: 'destroyed successfully'
  end

  private

  def post_params
    params.require(:post).permit(:title, tag_ids: [])
  end
end

#  ==== CSS ====

UniRails.css <<~CSS
html { background-color:#EEE; } body { width:500px; height:700px; margin:auto; background-color:white; padding:1rem; } .errors { color: red; } .field_with_errors { color: red; display: inline; } table { width:100%; table-layout: fixed; th, td { text-align:left; padding: .5rem; border: 1px solid black; } .actions { a, .button_to { display: inline; } } }
CSS # ==== VIEWS ==== UniRails.register_view "posts/index.html.erb", <<~HTML
<p style="color: green"><%= notice %></p> <h1>Posts</h1> <p><%= link_to 'Create new post', new_post_path %></p> <table> <thead> <tr> <th>Title</th> <th>Tags</th> <th>Actions</th> </tr> </thead> <tbody> <% if @posts.present? %> <% @posts.each do |post| %> <tr> <td><%= post.title %></td> <td><%= post.tag_names.to_sentence %></td> <td class="actions"> <%= link_to 'Edit', edit_post_path(post) %> <%= button_to 'Destroy', post, method: :delete %> </td> </tr> <% end %> <% else %> <tr><td colspan="3">There are no posts</td></tr> <% end %> </tbody> </table>
HTML UniRails.register_view "posts/_form.html.erb", <<~HTML
<%= form_with model: post do |f| %> <p class="errors"><%= post.errors.full_messages.to_sentence %></p> <%= f.label :title %> <%= f.text_field :title %> <fieldset> <legend>tags</legend> <%= f.collection_check_boxes :tag_ids, Tag.all, :id, :name %> </fieldset> <p> <%= f.submit %> <%= link_to 'Cancel', :back %> </p> <% end %>
HTML UniRails.register_view "posts/new.html.erb", <<~HTML
<h1>New Post</h1> <%= render 'form', post: @post %>
HTML UniRails.register_view "posts/edit.html.erb", <<~HTML
<h1>Edit <%= @post.title %></h1> <%= render 'form', post: @post %>
HTML UniRails.run(Port: 3000)