# Terminal rails g scaffold feedback consumer:belongs_to rails g mannequin emote consumer:belongs_to remark:belongs_to emoji rails action_text:set up rails db:migrate
# fashions/consumer.rb class Consumer < ApplicationRecord # Embody default devise modules. Others out there are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_many :feedback, dependent: :destroy has_many :emotes, dependent: :destroy # has_many :emoted_comments, by means of: :emotes, class_name: "Remark" finish
# fashions/emote.rb class Emote < ApplicationRecord belongs_to :consumer belongs_to :remark finish
# fashions/emoji.rb class Emoji # [{key: emoji.png, text: Emoji}, {}] # Emoji.all def self.all self.new.all finish def all list_of_emojis finish non-public def list_of_emojis Dir.youngsters(emojis_path).map file finish def emojis_path Rails.root.be a part of('app', 'property', 'pictures', 'emojis') finish def emoji_hash(file) { key: file, textual content: humanized(file) } finish def humanized(file) basename(file).humanize finish def basename(file) File.basename(file, File.extname(file)) finish finish
# fashions/remark.rb class Remark < ApplicationRecord belongs_to :consumer has_rich_text :content material has_many :emotes, dependent: :destroy # has_many :emoters, by means of: :emotes, class_name: "Consumer" def emotes_size(key) self.emotes.choose e.emoji == key .dimension finish finish
# views/feedback/_form.html.erb <%= form_with(mannequin: remark, native: true) do |kind| %> <div class="area"> <%= kind.rich_text_area :content material %> </div> <div class="actions"> <%= kind.submit %> </div> <% finish %>
# views/feedback/index.html.erb <% @feedback.every do |remark| %> <div class="remark"> <%= remark.content material %> <em class="meta"> <%= remark.consumer.identify %> | <%= remark.created_at %> | <%= link_to 'Destroy', remark, methodology: :delete, information: { verify: 'Are you positive?' } %> </em> <div class="emojis"> <% Emoji.all.every do |emoji| %> <% dimension = remark.emotes_size(emoji[:key]) %> <%= link_to comment_emote_path(remark, emote: emoji[:key]), class: "emoji #{dimension.zero? ? 'emoji-gray' : ''}" do %> <%= image_tag File.be a part of('emojis', emoji[:key]), dimension: '25x25', title: emoji[:text] %> <%= content_tag :span, dimension, class: 'depend' %> <% finish %> <% finish %> </div> </div> <% finish %> <%= render 'kind', remark: Remark.new %>
# controllers/comments_controller.rb class CommentsController < ApplicationController before_action :set_comment, solely: :destroy def index @feedback = Remark.contains(:emotes).all finish def create @remark = current_user.feedback.new(comment_params) if @remark.save redirect_to comments_path, discover: 'Remark was efficiently created.' else render :new finish finish def destroy @remark.destroy redirect_to comments_url, discover: 'Remark was efficiently destroyed.' finish non-public def set_comment @remark = current_user.feedback.discover(params[:id]) finish def comment_params params.require(:remark).allow(:content material) finish finish
# controllers/emotes_controller.rb class EmotesController < ApplicationController def present remark = Remark.find_by(id: params[:comment_id]) emote = current_user.emotes.find_or_initialize_by(remark: remark, emoji: params[:emote]) if emote.new_record? emote.save else emote.destroy finish redirect_to root_path finish finish
# routes.rb assets :feedback do useful resource :emote, solely: :present finish
# db/migrate/20200202022753_create_emotes.rb class CreateEmotes < ActiveRecord::Migration[6.0] def change create_table :emotes do |t| t.belongs_to :consumer, null: false, foreign_key: true t.belongs_to :remark, null: false, foreign_key: true t.string :emoji, null: false t.timestamps finish finish finish
# feedback.scss .remark { border: 1px dashed grey; margin-bottom: 10px; padding: 10px; } .remark .meta, .remark .meta a { coloration: grey; } .emojis { margin-top: 10px; } .emoji img { padding: 5px; } .emoji.emoji-gray img { filter: grayscale(100%); } .emoji.emoji-gray img:hover { filter: grayscale(0%); } .emoji { place: relative; } .emoji .depend { place: absolute; high: 10; left: 0; padding: 3px; background-color: #269ba5; text-decoration: none; coloration: #ffffff; border-radius: 20px; font-size: 10px; }