mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-11-03 20:48:07 +00:00 
			
		
		
		
	- api to update name and email - api to change password - api to set profile pic - fixes update_attribute! deprecation warning - introducing active storage
This commit is contained in:
		@@ -6,6 +6,8 @@ inherit_from: .rubocop_todo.yml
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Metrics/LineLength:
 | 
					Metrics/LineLength:
 | 
				
			||||||
  Max: 150
 | 
					  Max: 150
 | 
				
			||||||
 | 
					RSpec/ExampleLength:
 | 
				
			||||||
 | 
					  Max: 10
 | 
				
			||||||
Documentation:
 | 
					Documentation:
 | 
				
			||||||
  Enabled: false
 | 
					  Enabled: false
 | 
				
			||||||
Style/FrozenStringLiteralComment:
 | 
					Style/FrozenStringLiteralComment:
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								Gemfile
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								Gemfile
									
									
									
									
									
								
							@@ -19,6 +19,11 @@ gem 'responders'
 | 
				
			|||||||
gem 'time_diff'
 | 
					gem 'time_diff'
 | 
				
			||||||
gem 'tzinfo-data'
 | 
					gem 'tzinfo-data'
 | 
				
			||||||
gem 'valid_email2'
 | 
					gem 'valid_email2'
 | 
				
			||||||
 | 
					# compress javascript config.assets.js_compressor
 | 
				
			||||||
 | 
					gem 'uglifier'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##-- for active storage --##
 | 
				
			||||||
 | 
					gem 'mini_magick'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##-- gems for database --#
 | 
					##-- gems for database --#
 | 
				
			||||||
gem 'pg'
 | 
					gem 'pg'
 | 
				
			||||||
@@ -40,7 +45,7 @@ gem 'jwt'
 | 
				
			|||||||
gem 'pundit'
 | 
					gem 'pundit'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##--- gems for pubsub service ---##
 | 
					##--- gems for pubsub service ---##
 | 
				
			||||||
# TODO investigate and remove this gem
 | 
					# https://karolgalanciak.com/blog/2019/11/30/from-activerecord-callbacks-to-publish-slash-subscribe-pattern-and-event-driven-design/
 | 
				
			||||||
gem 'wisper', '2.0.0'
 | 
					gem 'wisper', '2.0.0'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##--- gems for reporting ---##
 | 
					##--- gems for reporting ---##
 | 
				
			||||||
@@ -66,9 +71,7 @@ gem 'sentry-raven'
 | 
				
			|||||||
##-- TODO: move these gems to appropriate groups --##
 | 
					##-- TODO: move these gems to appropriate groups --##
 | 
				
			||||||
# remove this gem in favor of active storage -  github #158
 | 
					# remove this gem in favor of active storage -  github #158
 | 
				
			||||||
gem 'carrierwave-aws'
 | 
					gem 'carrierwave-aws'
 | 
				
			||||||
gem 'mini_magick'
 | 
					 | 
				
			||||||
gem 'sidekiq'
 | 
					gem 'sidekiq'
 | 
				
			||||||
gem 'uglifier'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
group :development do
 | 
					group :development do
 | 
				
			||||||
  gem 'annotate'
 | 
					  gem 'annotate'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@ class Api::V1::AgentsController < Api::BaseController
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def update
 | 
					  def update
 | 
				
			||||||
    @agent.update_attributes!(agent_params)
 | 
					    @agent.update!(agent_params)
 | 
				
			||||||
    render json: @agent
 | 
					    render json: @agent
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,7 @@ class Api::V1::CallbacksController < ApplicationController
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        fb_page = current_account.facebook_pages.find_by(page_id: fb_page_id)
 | 
					        fb_page = current_account.facebook_pages.find_by(page_id: fb_page_id)
 | 
				
			||||||
        if fb_page
 | 
					        if fb_page
 | 
				
			||||||
          fb_page.update_attributes!(
 | 
					          fb_page.update!(
 | 
				
			||||||
            user_access_token: @user_access_token,
 | 
					            user_access_token: @user_access_token,
 | 
				
			||||||
            page_access_token: page_detail['access_token']
 | 
					            page_access_token: page_detail['access_token']
 | 
				
			||||||
          )
 | 
					          )
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ class Api::V1::CannedResponsesController < Api::BaseController
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def update
 | 
					  def update
 | 
				
			||||||
    @canned_response.update_attributes!(canned_response_params)
 | 
					    @canned_response.update!(canned_response_params)
 | 
				
			||||||
    render json: @canned_response
 | 
					    render json: @canned_response
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,7 +22,7 @@ class Api::V1::ContactsController < Api::BaseController
 | 
				
			|||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def update
 | 
					  def update
 | 
				
			||||||
    @contact.update_attributes!(contact_params)
 | 
					    @contact.update!(contact_params)
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private
 | 
					  private
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										22
									
								
								app/controllers/api/v1/profiles_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								app/controllers/api/v1/profiles_controller.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					class Api::V1::ProfilesController < Api::BaseController
 | 
				
			||||||
 | 
					  before_action :fetch_user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def show
 | 
				
			||||||
 | 
					    render json: @user
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def update
 | 
				
			||||||
 | 
					    @user.update!(profile_params)
 | 
				
			||||||
 | 
					    render json: @user
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def fetch_user
 | 
				
			||||||
 | 
					    @user = current_user
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def profile_params
 | 
				
			||||||
 | 
					    params.require(:profile).permit(:email, :name, :password, :password_confirmation, :avatar)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -10,7 +10,6 @@
 | 
				
			|||||||
#  current_sign_in_ip     :string
 | 
					#  current_sign_in_ip     :string
 | 
				
			||||||
#  email                  :string
 | 
					#  email                  :string
 | 
				
			||||||
#  encrypted_password     :string           default(""), not null
 | 
					#  encrypted_password     :string           default(""), not null
 | 
				
			||||||
#  image                  :string
 | 
					 | 
				
			||||||
#  last_sign_in_at        :datetime
 | 
					#  last_sign_in_at        :datetime
 | 
				
			||||||
#  last_sign_in_ip        :string
 | 
					#  last_sign_in_ip        :string
 | 
				
			||||||
#  name                   :string           not null
 | 
					#  name                   :string           not null
 | 
				
			||||||
@@ -60,6 +59,9 @@ class User < ApplicationRecord
 | 
				
			|||||||
  # Used by the actionCable/PubSub Service we use for real time communications
 | 
					  # Used by the actionCable/PubSub Service we use for real time communications
 | 
				
			||||||
  has_secure_token :pubsub_token
 | 
					  has_secure_token :pubsub_token
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Uses active storage for the avatar
 | 
				
			||||||
 | 
					  has_one_attached :avatar
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # The validation below has been commented out as it does not
 | 
					  # The validation below has been commented out as it does not
 | 
				
			||||||
  # work because :validatable in devise overrides this.
 | 
					  # work because :validatable in devise overrides this.
 | 
				
			||||||
  # validates_uniqueness_of :email, scope: :account_id
 | 
					  # validates_uniqueness_of :email, scope: :account_id
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,7 @@ Rails.application.routes.draw do
 | 
				
			|||||||
        resources :inboxes, only: [:create]
 | 
					        resources :inboxes, only: [:create]
 | 
				
			||||||
      end
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      resource :profile, only: [:show, :update]
 | 
				
			||||||
      resources :accounts, only: [:create]
 | 
					      resources :accounts, only: [:create]
 | 
				
			||||||
      resources :inboxes, only: [:index, :destroy]
 | 
					      resources :inboxes, only: [:index, :destroy]
 | 
				
			||||||
      resources :agents, except: [:show, :edit, :new]
 | 
					      resources :agents, except: [:show, :edit, :new]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					# This migration comes from active_storage (originally 20170806125915)
 | 
				
			||||||
 | 
					class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
 | 
				
			||||||
 | 
					  def change
 | 
				
			||||||
 | 
					    create_table :active_storage_blobs do |t|
 | 
				
			||||||
 | 
					      t.string   :key,        null: false
 | 
				
			||||||
 | 
					      t.string   :filename,   null: false
 | 
				
			||||||
 | 
					      t.string   :content_type
 | 
				
			||||||
 | 
					      t.text     :metadata
 | 
				
			||||||
 | 
					      t.bigint   :byte_size,  null: false
 | 
				
			||||||
 | 
					      t.string   :checksum,   null: false
 | 
				
			||||||
 | 
					      t.datetime :created_at, null: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      t.index [ :key ], unique: true
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    create_table :active_storage_attachments do |t|
 | 
				
			||||||
 | 
					      t.string     :name,     null: false
 | 
				
			||||||
 | 
					      t.references :record,   null: false, polymorphic: true, index: false
 | 
				
			||||||
 | 
					      t.references :blob,     null: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      t.datetime :created_at, null: false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true
 | 
				
			||||||
 | 
					      t.foreign_key :active_storage_blobs, column: :blob_id
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										5
									
								
								db/migrate/20191209202758_remove_image_from_user.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								db/migrate/20191209202758_remove_image_from_user.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					class RemoveImageFromUser < ActiveRecord::Migration[6.0]
 | 
				
			||||||
 | 
					  def change
 | 
				
			||||||
 | 
					    remove_column :users, :image, :string
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										25
									
								
								db/schema.rb
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								db/schema.rb
									
									
									
									
									
								
							@@ -10,7 +10,7 @@
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
# It's strongly recommended that you check this file into your version control system.
 | 
					# It's strongly recommended that you check this file into your version control system.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ActiveRecord::Schema.define(version: 2019_12_04_192301) do
 | 
					ActiveRecord::Schema.define(version: 2019_12_09_202758) do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # These are extensions that must be enabled in order to support this database
 | 
					  # These are extensions that must be enabled in order to support this database
 | 
				
			||||||
  enable_extension "plpgsql"
 | 
					  enable_extension "plpgsql"
 | 
				
			||||||
@@ -21,6 +21,27 @@ ActiveRecord::Schema.define(version: 2019_12_04_192301) do
 | 
				
			|||||||
    t.datetime "updated_at", null: false
 | 
					    t.datetime "updated_at", null: false
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  create_table "active_storage_attachments", force: :cascade do |t|
 | 
				
			||||||
 | 
					    t.string "name", null: false
 | 
				
			||||||
 | 
					    t.string "record_type", null: false
 | 
				
			||||||
 | 
					    t.bigint "record_id", null: false
 | 
				
			||||||
 | 
					    t.bigint "blob_id", null: false
 | 
				
			||||||
 | 
					    t.datetime "created_at", null: false
 | 
				
			||||||
 | 
					    t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
 | 
				
			||||||
 | 
					    t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  create_table "active_storage_blobs", force: :cascade do |t|
 | 
				
			||||||
 | 
					    t.string "key", null: false
 | 
				
			||||||
 | 
					    t.string "filename", null: false
 | 
				
			||||||
 | 
					    t.string "content_type"
 | 
				
			||||||
 | 
					    t.text "metadata"
 | 
				
			||||||
 | 
					    t.bigint "byte_size", null: false
 | 
				
			||||||
 | 
					    t.string "checksum", null: false
 | 
				
			||||||
 | 
					    t.datetime "created_at", null: false
 | 
				
			||||||
 | 
					    t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  create_table "attachments", id: :serial, force: :cascade do |t|
 | 
					  create_table "attachments", id: :serial, force: :cascade do |t|
 | 
				
			||||||
    t.string "file"
 | 
					    t.string "file"
 | 
				
			||||||
    t.integer "file_type", default: 0
 | 
					    t.integer "file_type", default: 0
 | 
				
			||||||
@@ -207,7 +228,6 @@ ActiveRecord::Schema.define(version: 2019_12_04_192301) do
 | 
				
			|||||||
    t.string "unconfirmed_email"
 | 
					    t.string "unconfirmed_email"
 | 
				
			||||||
    t.string "name", null: false
 | 
					    t.string "name", null: false
 | 
				
			||||||
    t.string "nickname"
 | 
					    t.string "nickname"
 | 
				
			||||||
    t.string "image"
 | 
					 | 
				
			||||||
    t.string "email"
 | 
					    t.string "email"
 | 
				
			||||||
    t.json "tokens"
 | 
					    t.json "tokens"
 | 
				
			||||||
    t.integer "account_id", null: false
 | 
					    t.integer "account_id", null: false
 | 
				
			||||||
@@ -223,6 +243,7 @@ ActiveRecord::Schema.define(version: 2019_12_04_192301) do
 | 
				
			|||||||
    t.index ["uid", "provider"], name: "index_users_on_uid_and_provider", unique: true
 | 
					    t.index ["uid", "provider"], name: "index_users_on_uid_and_provider", unique: true
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
 | 
				
			||||||
  add_foreign_key "contact_inboxes", "contacts"
 | 
					  add_foreign_key "contact_inboxes", "contacts"
 | 
				
			||||||
  add_foreign_key "contact_inboxes", "inboxes"
 | 
					  add_foreign_key "contact_inboxes", "inboxes"
 | 
				
			||||||
  add_foreign_key "users", "users", column: "inviter_id", on_delete: :nullify
 | 
					  add_foreign_key "users", "users", column: "inviter_id", on_delete: :nullify
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								spec/assets/avatar.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								spec/assets/avatar.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 27 KiB  | 
							
								
								
									
										80
									
								
								spec/controllers/api/v1/profiles_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								spec/controllers/api/v1/profiles_controller_spec.rb
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					require 'rails_helper'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RSpec.describe 'Profile API', type: :request do
 | 
				
			||||||
 | 
					  let(:account) { create(:account) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe 'GET /api/v1/profile' do
 | 
				
			||||||
 | 
					    context 'when unauthenticated user' do
 | 
				
			||||||
 | 
					      it 'returns unauthorized' do
 | 
				
			||||||
 | 
					        get '/api/v1/profile'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expect(response).to have_http_status(:unauthorized)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    context 'when it authenticated user' do
 | 
				
			||||||
 | 
					      let(:agent) { create(:user, account: account, role: :agent) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it 'returns current user information' do
 | 
				
			||||||
 | 
					        get '/api/v1/profile',
 | 
				
			||||||
 | 
					            headers: agent.create_new_auth_token,
 | 
				
			||||||
 | 
					            as: :json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expect(response).to have_http_status(:success)
 | 
				
			||||||
 | 
					        json_response = JSON.parse(response.body)
 | 
				
			||||||
 | 
					        expect(json_response['id']).to eq(agent.id)
 | 
				
			||||||
 | 
					        expect(json_response['email']).to eq(agent.email)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe 'PUT /api/v1/profile' do
 | 
				
			||||||
 | 
					    context 'when unauthenticated user' do
 | 
				
			||||||
 | 
					      it 'returns unauthorized' do
 | 
				
			||||||
 | 
					        put '/api/v1/profile'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expect(response).to have_http_status(:unauthorized)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    context 'when it authenticated user' do
 | 
				
			||||||
 | 
					      let(:agent) { create(:user, account: account, role: :agent) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it 'updates the name & email' do
 | 
				
			||||||
 | 
					        put '/api/v1/profile',
 | 
				
			||||||
 | 
					            params: { profile: { name: 'test', 'email': 'test@test.com' } },
 | 
				
			||||||
 | 
					            headers: agent.create_new_auth_token,
 | 
				
			||||||
 | 
					            as: :json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expect(response).to have_http_status(:success)
 | 
				
			||||||
 | 
					        json_response = JSON.parse(response.body)
 | 
				
			||||||
 | 
					        agent.reload
 | 
				
			||||||
 | 
					        expect(json_response['id']).to eq(agent.id)
 | 
				
			||||||
 | 
					        expect(json_response['email']).to eq(agent.email)
 | 
				
			||||||
 | 
					        expect(agent.email).to eq('test@test.com')
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it 'updates the password' do
 | 
				
			||||||
 | 
					        put '/api/v1/profile',
 | 
				
			||||||
 | 
					            params: { profile: { password: 'test123', password_confirmation: 'test123' } },
 | 
				
			||||||
 | 
					            headers: agent.create_new_auth_token,
 | 
				
			||||||
 | 
					            as: :json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expect(response).to have_http_status(:success)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it 'updates avatar' do
 | 
				
			||||||
 | 
					        # no avatar before upload
 | 
				
			||||||
 | 
					        expect(agent.avatar.attached?).to eq(false)
 | 
				
			||||||
 | 
					        file = fixture_file_upload(Rails.root.join('spec/assets/avatar.png'), 'image/png')
 | 
				
			||||||
 | 
					        put '/api/v1/profile',
 | 
				
			||||||
 | 
					            params: { profile: { name: 'test', 'email': 'test@test.com', avatar: file } },
 | 
				
			||||||
 | 
					            headers: agent.create_new_auth_token
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        expect(response).to have_http_status(:success)
 | 
				
			||||||
 | 
					        agent.reload
 | 
				
			||||||
 | 
					        expect(agent.avatar.attached?).to eq(true)
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -18,5 +18,9 @@ FactoryBot.define do
 | 
				
			|||||||
    after(:build) do |user, evaluator|
 | 
					    after(:build) do |user, evaluator|
 | 
				
			||||||
      user.skip_confirmation! if evaluator.skip_confirmation
 | 
					      user.skip_confirmation! if evaluator.skip_confirmation
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    trait :with_avatar do
 | 
				
			||||||
 | 
					      avatar { Rack::Test::UploadedFile.new('spec/assets/avatar.png', 'image/png') }
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user