class BeautifulSorceryGenerator

encoding : utf-8

Public Instance Methods

install_sorcery() click to toggle source

argument :model, :type => :string, :desc => “Name of model (ex: User)”

# File lib/generators/beautiful_sorcery_generator.rb, line 10
  def install_sorcery
    model = "User"
    view_path = "app/views/"

    if !File.read('Gemfile').include?("sorcery")
      gem("sorcery", "0.16.0")
    end

    Bundler.with_unbundled_env do
      run "bundle install"
    end

    raise "Model must be specified" if model.blank?

    # Install sorcery
    generate("sorcery:install", "remember_me reset_password user_activation brute_force_protection external --model #{model}")

    # If exist users migration just add columns
    create_user_migration = Dir.glob("db/migrate/*create_users.rb").first
    if create_user_migration
      already_email = File.read(create_user_migration).include?(":email")
      sorcery_core_file = Dir.glob("db/migrate/*sorcery_core.rb").first
      File.open(sorcery_core_file, "w+") do |f|
        f.write("class SorceryCore < ActiveRecord::Migration[6.1]
  def change
    #{(already_email ? '' : 'add_column :users, :email, :string')}
    add_column :users, :crypted_password, :string
    add_column :users, :salt, :string

    #{(already_email ? '' : 'add_index :users, :email, unique: true')}
  end
end")
      end
    end

    # Generate mailer
    copy_file("app/mailers/user_mailer.rb")

    # Install controllers
    copy_file("app/controllers/user_sessions_controller.rb")

    # ===== Controller
    inject_into_file("app/controllers/users_controller.rb",
 "\n
  skip_before_action :require_login, only: [:new, :create, :activate]
\n", after: "< BeautifulController")

    inject_into_file("app/controllers/users_controller.rb",
   "def activate
    if @user = User.load_from_activation_token(params[:id])
      @user.activate!
      redirect_to(login_path, :notice => 'User was successfully activated.')
    else
      not_authenticated
    end
  end\n\n  ", before: "private")

    # ====== Model
    # Add password & password_confirmation in model
    inject_into_file("app/models/user.rb",
    "\n
  validates :password, length: { minimum: 3 }, if: -> { new_record? || changes[:crypted_password] }
  validates :password, confirmation: true, if: -> { new_record? || changes[:crypted_password] }
  validates :password_confirmation, presence: true, if: -> { new_record? || changes[:crypted_password] }

  before_update :setup_activation, if: -> { email_changed? }
  after_update :send_activation_needed_email!, if: -> { previous_changes['email'].present? }\n",
                     after: "ApplicationRecord")

    inject_into_file("app/models/user.rb", ":password,:password_confirmation,", :after => "def self.permitted_attributes\n    return ")

    # ====== Views
    inject_into_file("app/views/users/_form.html.erb",
    '  <div class="form-group">
    <%= f.label :password, t(\'app.models.user.bs_attributes.password\', :default => \'password\').capitalize, :class => "control-label" %><br />
    <%= f.password_field :password, :class => "form-control" %>
  </div>
  <div class="form-group">
    <%= f.label :password_confirmation, t(\'app.models.user.bs_attributes.password_confirmation\', :default => \'password_confirmation\').capitalize, :class => "control-label" %><br />
    <%= f.password_field :password_confirmation, :class => "form-control" %>
  </div>', before: '<!-- Beautiful_scaffold - AddField - Do not remove -->')

    # Install all views for login/logout
    directory "app/views/login_logout", "app/views"

    # Domain in action_mailer
    for current_env in ['production', 'development', 'test']
      inject_into_file("config/environments/#{current_env}.rb",  "  config.action_mailer.default_url_options = { :host => 'localhost:3000' }", :after => "Rails.application.configure do\n" )
    end

    # In model
    #remove_file("app/models/user.rb") # remove generated by sorcery
    #copy_file("app/models/user.rb") # copy BS version ;)

    # Limited access
    inject_into_file("app/controllers/beautiful_controller.rb",
                     "\n  before_action :require_login, except: [:dashboard]\n",
                     :after => 'layout "beautiful_layout"' + "\n")

    inject_into_file("config/initializers/sorcery.rb",
                     "\nuser.user_activation_mailer = UserMailer\n",
                     :after => "# user.user_activation_mailer =\n")

    # Routes (session)
    inject_into_file("config/routes.rb",
                     '
  resources :user_sessions, only: [:create]
  get "login" => "user_sessions#new", :as => :login
  post "logout" => "user_sessions#destroy", :as => :logout' + "\n\n\n",
                     :after => "Rails.application.routes.draw do\n")

    # Activate
    inject_into_file("config/routes.rb", " do
    member do
      get :activate
    end
  end", after: 'resources :users, concerns: :bs_routes')

    copy_file("#{view_path}partials/_login_logout_register.html.erb", "#{view_path}layouts/_login_logout_register.html.erb")

    # Sign in sign out
    inject_into_file("#{view_path}layouts/beautiful_layout.html.erb",
                     "\n<%= render :partial => 'layouts/login_logout_register' %>\n",
                     :after => "<!-- Beautiful_scaffold - Signin - Do not remove -->")

    say "Beautiful-Scaffold enable 'user_activation' sorcery module for you, so when you sign up, find in logs the activation link. You can't sign in yourself until you activate the account"
  end