This is tutorial in Serbian language, creating simple shop with Rails 6 and Bitcoin, without JavaScript (or to not depends on JavaScript).
Prvi u seriji od 3 tutoriala u kojima cemo napraviti kompletnu prodavnicu, bez funkcija koje necemo koristiti, bez online wallet-a, privatnih kljuceva. Siguran i jednostavan nacin, koristeci BIP32 Master Public Key. Podrazumeva se osnovno znanje Ruby on Rails i MVC.
U prvom delu napravicemo novu aplikaciju, korisnike, proizvode i kopru. U drugom delu porudzbine i placanje, i u trecem delu izgled sajta, pagination, i priprema za production env.
Nova aplikacija
Kreiraj novu rails aplikaciju (istraziti rails new komandu, kao i --no-javascript i --api opcije).
rails new example-shop
Otvorite Gemfile i u njega dodajte sledece:
gem 'devise'
gem 'bulma'
Ovo ce instalirati gemove za autentikaciju (devise) i za stil (bulma).
Nakon toga kucajte bundle install
za instaliranje gemova.
Novi Korisnik
rails g devise:install
rails g devise user
rails g controller registrations
Ovo ce integrisati devise u vasu aplikaciju, dodati model i tabelu :users,
i napraviti novi kontroler za registracije. Otvorite Registrations Controller:
class RegistrationsController < Devise::RegistrationsController
private
def sign_up_params
params.require(:user).permit(:name, :address, :country, :email, :password, :password_confirmation)
end
def account_update_params
params.require(:user).permit(:name, :address, :country, :email, :password, :password_confirmation, :current_password)
end
end
Registrations Controller proizilazi iz Devise::Registrations, pa u njemu menjamo params, da bi smo
dodali nova polja (:name, :address, :country). Nakon toga napravite novu migraciju:
rails g migration add_fields_to_users
class AddFieldsToUsers < ActiveRecord::Migration[6.0]
def change
add_column :users, :name, :string, null: false, default: ""
add_column :users, :country, :string, null: false, default: ""
add_column :users, :address, :text
end
end
Za kraj izvrsite komandu rails db:migrate
.
Otvoride model User i dodajte sledece:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
validates :name, length: { maximum: 16, too_long: "%{count} chars is maximum for User name."}
validates :country, length: { maximum: 20, too_long: "%{count} chars is maximum for User country."}
validates :address, length: { maximum: 75, too_long: "%{count} chars is maximum for User address."}
has_many :products
end
Provera da li je neko polje validno moze da se definise u modelu ili direktno u DB (migrations).
Ako je polje obavezno za sve, definisemo null: false, ali nekad je polje obavezno za jednu grupu
korisnika, dok za drugu nije. Zato sve provere treba definisati u modelu.
Dodati Proizvode
Rails scaffold automatski napravi model, kontroler, kao i views.
rails g scaffold product title description:text photo price:decimal user_id:integer published:boolean
Otvorite ProductsController i promenite kod da izgleda ovako:
class ProductsController < ApplicationController
before_action :authenticate_user!, except: [:show, :index]
before_action :set_product, only: [:show, :update, :destroy, :edit]
def index
@products = Product.all
end
def show
end
def new
@product = current_user.products.build
end
def edit
end
def create
@product = current_user.products.build(product_params)
if @product.save
redirect_to @product, notice: "Product #{@product.title} has been created."
else
render :new
end
end
def update
if @product.update(product_params)
redirect_to @product, notice: "Product #{@product.title} has been updated."
else
render :edit
end
end
def destroy
@product.published = false if @product.user_id == current_user.id
redirect_to root_path, notice: 'Product was successfully destroyed.'
end
private
def set_product
@product = Product.find(params[:id])
end
def product_params
params.require(:product).permit(:title, :price, :description, :photo, :user_id, :published)
end
end
Promenite model Product da izleda:
class Product < ApplicationRecord
belongs_to :user
validates :title, :price, :description, :photo, :user_id, :published, presence: true
validates :price, length: { maximum: 7 }
validates :title, length: { maximum: 140, too_long: "Title is too long! [%{count}] chars is maximum."}
validates :description, length: { maximum: 1000, too_long: "Description is too long! [%{count}] chars is maximum."}
end
Na kraju migracije:
class CreateProducts < ActiveRecord::Migration[6.0]
def change
create_table :products do |t|
t.string :title, null: false, default: ""
t.decimal :price, null: false, default: 0
t.text :description
t.string :photo
t.boolean :published, null:false, default: true
t.timestamps
end
end
end
Izvrsite rails db:migrate
i kreirali ste Products za vasu aplikaciju!
Shopping Cart
Shopping Cart je nezaobilazni deo svake prodavnice. Za to su nam potrebni
Cart i CartItem. Ponovo koristimo scaffold, i pocinjemo sa Cart modelom.
rails g scaffold cart
Otvorite CartsController i neka izgleda ovako:
class CartsController < ApplicationController
rescue_from ActiveRecord::RecordNotFound, with: :invalid_cart
before_action :set_cart, except: [:create, :new]
def index
@carts = list_cart_products
end
def new
@cart = current_user.carts.build
end
def create
@cart = current_user.carts.build(cart_params)
if @cart.save
redirect_to @cart
else
render :new
end
end
def destroy
if current_cart.id == session[:cart_id]
@cart.destroy
session[:cart_id] = session[:token] = nil
set_cart and redirect_to root_url, notice: 'Your cart is empty!'
end
end
private
def list_cart_products
CartItem.where(cart_id: session[:cart_id]).all
end
def invalid_cart
logger.error "Attempt to access invalid cart with ID: #{params[:id]}"
redirect_to root_path, notice: "Cart doesn't exist!"
end
def cart_params
params.require(:cart).permit(:token)
end
end
Kako bi odrzali korpu i za korisnike koji nisu registrovani, koristimo :sessions.
Takodje koristimo i :token, koji ce kasnije sluziti za friendly-id gem kao rute,
i svaki model verifikuje token (cart, order, payment)
Sada otvorite Cart model i dodajte sledece:
class Cart < ApplicationRecord
has_many :cart_items, dependent: :destroy
validates :token, presence: true
def add(product)
cart_item = cart_items.find_by(product_id: product.id)
cart_item ? cart_item.quantity += 1 : cart_item = cart_items.build(product_id: product.id)
end
def total_price
cart_items.to_a.sum { |item| item.total_price }
end
end
Otvorite concerns u folderu models i napravite shopping_cart.rb.
U njega dodajte sledece:
module ShoppingCart
private
def set_cart
begin
@cart = Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
@cart = Cart.create(token: generate_token)
session[:token] = @cart.token
session[:cart_id] = @cart.id
end
end
def generate_token
SecureRandom.urlsafe_base64
end
end
Otvorite ApplicationController i dodajte sledece:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
include ShoppingCart
before_action :set_cart
helper :all
def current_cart
Cart.find(session[:cart_id])
end
end
Sada napravite CartItem, ponovo uz pomoc scaffold-a:
rails g scaffold cart_item
Otvorite CartItems Controller i dodajte sledece:
class CartItemsController < ApplicationController
before_action :set_cart
before_action :set_cart_item, except: [:index, :create]
def index
@cart_item = CartItem.find_by(cart_id: session[:cart_id])
end
def show
@cart_item = CartItem.find(params[:id])
end
def new
@cart_item = CartItem.new
end
def create
@product = Product.find(params[:product_id])
@cart_item = @cart.add(@product)
@cart_item.product_id = @product.id
if @cart_item.save
redirect_to carts_path, notice: "#{@cart_item.product.title} added to cart for $#{@cart_item.total_price}"
else
render :new
end
end
def destroy
if @cart_item.cart_id == @cart.id
@cart.destroy
set_cart and redirect_to @cart, notice: "#{@cart_item.product.title} has been removed from cart!"
end
end
private
def set_cart_item
@cart_item = CartItem.find_by(id: params[:id], cart_id: @cart.id)
end
def cart_item_params
params.require(:cart_item).permit(:product_id, :cart_id, :quantity, :total_price)
end
end
Sada otvorite model CartItem i dodajte:
class CartItem < ApplicationRecord
belongs_to :cart
belongs_to :product
def total_price
product.price.to_i * quantity.to_i
end
end
I to je sve za prvi deo! Sada imamo potpuno funkcionalne korisnike, proizvode i korpu.
U drugom delu dodacemo porudzbine i placanje Bitcoinom, kao i izgled sajta koristeci bulmu ili bootstrap, po vasem izboru.
Ostavite wordpress i woo-commerce, korstite Ruby on Rails za online prodavnicu.
Top comments (0)