플랫코인

34039 단어
이 앱은 Flatiron School Sinatra 프로젝트로 개발되었습니다. 저는 사용자가 암호화폐 포트폴리오 구축을 연습하고 가짜 돈(무료 FlatCoins 10,000개)을 사용하여 실시간으로 시장에 반응할 수 있도록 돕기 위해 이 앱을 개발했습니다. 또한 순위표 상단에서 자신의 자리를 차지하기 위해 친구나 동료와 경쟁할 수도 있습니다.
이 앱은 API를 통해 지속적으로 코인 가격을 가져옵니다. 이전 프로젝트의 코드를 재사용하고 있습니다.

Note: Before even sketching an app you should first research the right API, play around and see what data can you get from it. In my case I used CoinGecko.



Sinatra Activerecord 설정: 가장 중요한 세 가지 보석인 activerecord, sinatra-activerecord 및 rake를 추가해야 합니다.Gemfile
source 'http://rubygems.org'
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

gem 'sinatra'
gem 'activerecord', '~> 6.0.0', :require => 'active_record'
gem 'sinatra-activerecord', :require => 'sinatra/activerecord'
gem 'rake'
gem 'require_all'
gem 'sqlite3'
gem 'thin'
gem 'shotgun'
gem 'pry'
gem 'bcrypt'
gem "tux"
gem 'net-http'
gem 'open-uri'
gem 'json'
gem 'tty-prompt'

group :test do
  gem 'capybara'
  gem 'rack-test'
  gem 'database_cleaner'
end


데이터베이스에 대한 연결 설정:environment.rb
ENV['SINATRA_ENV'] ||= "development"

require 'net/http'
require 'open-uri'
require 'json'
require 'tty-prompt'
require 'bundler/setup'
Bundler.require(:default, ENV['SINATRA_ENV'])

ActiveRecord::Base.establish_connection(ENV['SINATRA_ENV'].to_sym)

require_all 'app'

database.yml
default: &default
  adapter: 'sqlite3'
  database: 'db/development.sqlite'

development:
  <<: *default

test:
  <<: *default
  database: 'db/test.sqlite'

config.ru
require './config/environment'

if ActiveRecord::Base.connection.migration_context.needs_migration?
  raise 'Migrations are pending. Run `rake db:migrate` to resolve the issue.'
end

use Rack::MethodOverride
run ApplicationController
use UsersController
use TradesController


Rake는 신속하게 파일을 만들고 자동화된 작업을 설정할 수 있는 기능을 제공합니다.Rakefile
ENV["SINATRA_ENV"] ||= "development"

require_relative './config/environment'
require 'sinatra/activerecord/rake'

users용 테이블과 trades용 테이블 두 개를 만들어야 했습니다. 마이그레이션을 실행한 후 내 스키마는 다음과 같습니다.schema.rb
ActiveRecord::Schema.define(version: 2021_03_22_162004) do

  create_table "trades", force: :cascade do |t|
    t.text "coin_name"
    t.decimal "current_price"
    t.integer "quantity"
    t.integer "user_id"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

  create_table "users", force: :cascade do |t|
    t.string "first_name"
    t.string "last_name"
    t.text "email"
    t.string "password_digest"
    t.decimal "balance"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

end


모델:
나의 주된 어려움은 올바른 모델을 정의하는 것이었습니다. 사용자의 FlatCoin 잔액, 거래 및 포트폴리오 가치를 어떻게 추적할 수 있습니까? 사용자와 거래를 데이터베이스에 확실히 저장하려면 필요하다는 것을 알고 있었지만 암호 화폐 가치는 어떻습니까? Cryptocurrency 값은 밀리초마다 변동하므로 데이터베이스에서 매번 가격을 저장하고 계속 업데이트하는 것이 이치에 맞지 않습니다. 대신 현재 가격이 필요할 때마다 API 호출을 할 수 있습니다.api.rbcryptocurrency.rb는 이전 프로젝트의 사본일 뿐입니다.user.rb
class User < ActiveRecord::Base
  has_many :trades

  validates_uniqueness_of :email
  validates_presence_of :first_name, :last_name, :email
  has_secure_password

end

trade.rb
class Trade < ActiveRecord::Base
    belongs_to :user 
end


견해:layout.erb는 앱의 기본 레이아웃을 생성하고 index.erb는 랜딩 페이지입니다.
사용자 하위 폴더는 balance.erb , login.erb , logout.erbsignup.erb 를 처리합니다.
거래 하위 폴더 핸들 all.erb , confirmation.erb , edit.erb , leaderboard.erb , new.erb , pick.erb , rejected.erbsell.erb .
GitHub에서 코드를 확인할 수 있습니다!

컨트롤러:helpers에서 application_controller.rb를 정의하면 logged_in?를 사용하여 앱에서 로직을 작동할 수 있습니다. 이 프로젝트에서 작업할 때 좋은 점은 tux를 사용하여 내 데이터베이스를 테스트하고 shotgun를 실행하여 내 앱을 실시간으로 테스트할 수 있다는 것입니다.application_controller.rb
require './config/environment'

class ApplicationController < Sinatra::Base

  configure do
    set :public_folder, 'public'
    set :views, 'app/views'
    enable :sessions
    set :session_secret, "aYxiNrafm3ScE4xfa91z2azkuUGJ720y"
  end

  get '/' do
    erb :index
  end

  helpers do

    def logged_in?
      !!current_user
    end

    def current_user
      @current_user ||= User.find_by(id: session[:user_id]) if session[:user_id]
    end

  end

end

trades_controller.rb
class TradesController < ApplicationController

    get '/trade' do
        if logged_in?
          erb :'trades/pick'
        else
          redirect to '/'
        end
    end

    post '/trade/new_trade' do
        @coin_id = params[:coin_id] 
        redirect to "/trade/#{@coin_id}"
    end

    get '/trade/:id' do
        if logged_in?
          Api.new.get_top_20_cryptocurrencies 
          @coin = Cryptocurrency.find_by_id(params[:id])
          if @coin != nil
            erb :'trades/new'
          else
            redirect to '/'
          end
        else
          redirect to '/'
        end
    end

    post '/trade/status' do
        if params[:quantity].to_i > 0
            @trade = current_user.trades.build(coin_name: params[:coin_name], current_price: params[:current_price], quantity: params[:quantity])
            @new_balance = current_user.balance - (params[:quantity].to_i*params[:current_price].to_f)
            if @new_balance > 0
                current_user.update(balance: @new_balance)
                @trade.save
                erb :'trades/confirmation'
            else
                erb :'trades/rejected'
            end
        else
            redirect to '/'
        end
    end

    get '/trades' do
        if logged_in?
          @trades = Trade.all
          erb :'trades/all'
        else
          redirect to '/'
        end
    end

    get '/trades/edit/:id' do
        if logged_in?
            @trade = Trade.find_by_id(params[:id])
            if @trade && @trade.user == current_user
                erb :'trades/edit'
            else
                redirect to '/users/balance'
            end
        else
            redirect to '/'
        end
    end

    patch '/trades/edit/:id' do
        if logged_in?
            @trade = Trade.find_by_id(params[:id])
            if @trade && @trade.user == current_user
                @trade.update(coin_name: params[:coin_name], current_price: params[:current_price], quantity: params[:quantity])
                redirect to '/users/balance'
            else
                redirect to '/users/balance'
            end
        else
            redirect to '/'
        end
    end

    get '/trades/sell/:id' do
        if logged_in?
            @trade = Trade.find_by_id(params[:id])
            if @trade && @trade.user == current_user
                Api.new.get_top_20_cryptocurrencies
                coin_name = @trade.coin_name
                @updated_coin = Cryptocurrency.find_by_name(coin_name)
                @new_balance = current_user.balance + (@trade.quantity.to_i * @updated_coin.current_price.to_f)
                erb :'trades/sell'
            else
                redirect to '/users/balance'
            end
        else
            redirect to '/'
        end
    end

    delete '/trades/sell/:id/delete' do
        puts params
        if logged_in?
          @trade = Trade.find_by_id(params[:id])
          if @trade && @trade.user == current_user
            current_user.update(balance: params[:new_balance])
            @trade.delete
          end
          redirect to '/users/balance'
        else
          redirect to '/'
        end
    end

    get '/leaderboard' do
        if logged_in?
          @users = User.all
          erb :'trades/leaderboard'
        else
          redirect to '/'
        end
    end

end

users_controller.rb
class UsersController < ApplicationController
    get '/users/balance' do
      if logged_in?
        @trades = current_user.trades.all
        erb :'users/balance'
      else
        redirect to '/'
      end
    end

    get '/signup' do
      if !logged_in?
        erb :'users/signup', locals: {message: "Please sign up before you sign in"}
      else
        redirect to '/'
      end
    end

    post '/signup' do
      if params[:first_name] == "" || params[:last_name] == "" || params[:email] == "" || params[:password] == ""
        redirect to '/signup'
      else
        @user = User.new(:first_name => params[:first_name], :last_name => params[:last_name], :email => params[:email], :password => params[:password])
        @user.balance = 10000 # Free '$10000' for signing up!
        @user.save
        session[:user_id] = @user.id
        redirect to '/'
      end
    end

    get '/login' do
      if !logged_in?
        erb :'users/login'
      else
        redirect to '/'
      end
    end

    post '/login' do
      user = User.find_by(:email => params[:email])
      if user && user.authenticate(params[:password])
        session[:user_id] = user.id
        redirect to '/'
      else
        redirect to '/signup'
      end
    end

    get '/logout' do
      if logged_in?
        session.destroy
        redirect to '/'
      else
        redirect to '/'
      end
    end
end


이 프로젝트는 매우 치열했지만 함께 할 수 있어서 정말 기쁩니다. API, html 및 데이터베이스를 명확하게 이해하는 것은 대화형 앱을 구축하는 데 중요합니다.
내 프로젝트의 짧은 비디오를 확인하십시오.
여기GitHub에서 프로젝트를 확인하세요!

좋은 웹페이지 즐겨찾기