Ruby%on%Rails% by#@tonytonyjan Ruby%on%Rails% - - PowerPoint PPT Presentation

ruby on rails
SMART_READER_LITE
LIVE PREVIEW

Ruby%on%Rails% by#@tonytonyjan Ruby%on%Rails% - - PowerPoint PPT Presentation

Ruby%on%Rails% by#@tonytonyjan Ruby%on%Rails% %,% 1 / /tonytonyjan tonytonyjan.net Ruby-on-Rails-


slide-1
SLIDE 1

Ruby%on%Rails%

  • by#@tonytonyjan
Ruby%on%Rails%%,% 1
slide-2
SLIDE 2

//tonytonyjan

  • tonytonyjan.net
  • Ruby-on-Rails-
  • TJDict-Chrome-
  • Rails-Girls-Taipei-1~5-
Ruby%on%Rails%%,% 2
slide-3
SLIDE 3
  • Ruby&(Rails)
  • C&(Qt)
  • Java&(Swing)
  • Network&Programming
  • Informa?on&Retrieval
Ruby%on%Rails%%,% 3
slide-4
SLIDE 4
  • RubyConf*Brazil*2015*
  • Confoo*Canada*2015*
  • Ruby*Kaigi*Japan*2014*
  • Yahoo*Hack*Taiwan*2013*
Ruby%on%Rails%%,% 4
slide-5
SLIDE 5

!RoR!

task '' => 'Rails' task 'Rails' => %w[Ruby CLI RDBMS Git] task '' => ''

Ruby%on%Rails%%,% 5
slide-6
SLIDE 6
Ruby%on%Rails%%,% 6
slide-7
SLIDE 7

!gem

Ruby%on%Rails%%,% 7
slide-8
SLIDE 8

User%Story

Ruby%on%Rails%%,% 8
slide-9
SLIDE 9

User%Story%*%

Ruby%on%Rails%%,% 9
slide-10
SLIDE 10

User%Story%*%

Ruby%on%Rails%%,% 10
slide-11
SLIDE 11
  • Spree
  • ror_ecommerce
  • Piggybak
  • mount4carrierwave4
Ruby%on%Rails%%,% 11
slide-12
SLIDE 12
  • Ruby%on%Rails%%,%
12
slide-13
SLIDE 13
  • Ruby%on%Rails%%,%
13
slide-14
SLIDE 14
  • "#>"/products
  • "#>"/products/:id
  • "#>"/cart
  • "#>"/orders/new
  • "#>"/orders/:id
  • "#>"/admin/*
Ruby%on%Rails%%,% 14
slide-15
SLIDE 15
  • git clone https://github.com/tonytonyjan/my_cart

cd my_cart rails s

Ruby%on%Rails%%,% 15
slide-16
SLIDE 16
  • $ bin/rake routes

Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show cart GET /cart(.:format) carts#show

Ruby%on%Rails%%,% 16
slide-17
SLIDE 17

# config/routes.rb root 'products#index' resources :products, only: :show resource :cart, only: :show

Ruby%on%Rails%%,% 17
slide-18
SLIDE 18

ERD

Ruby%on%Rails%%,% 18
slide-19
SLIDE 19

ERD

Ruby%on%Rails%%,% 19
slide-20
SLIDE 20
  • 1.

2. 3.

Ruby%on%Rails%%,% 20
slide-21
SLIDE 21 Ruby%on%Rails%%,% 21
slide-22
SLIDE 22
  • Ruby%on%Rails%%,%
22
slide-23
SLIDE 23 Ruby%on%Rails%%,% 23
slide-24
SLIDE 24
  • Ruby%on%Rails%%,%
24
slide-25
SLIDE 25 Ruby%on%Rails%%,% 25
slide-26
SLIDE 26
  • Agile'Web'Development'with'Rails'
  • ror_ecommerce'
  • SpreePiggybak''Cart'en>ty'Order'
Ruby%on%Rails%%,% 26
slide-27
SLIDE 27
  • rails g model product name description:text price:decimal stock:integer
rails g model order name address status payment_method rails g model cart rails g model line_item \
  • rder:references cart:references product:references \
unit_price:decimal quantity:integer Ruby%on%Rails%%,% 27
slide-28
SLIDE 28
  • # app/models/cart.rb
class Cart has_many :line_items end # app/models/product.rb class Product has_many :line_items end # app/models/order.rb class Order has_many :line_items has_many :products, through: :line_items end Ruby%on%Rails%%,% 28
slide-29
SLIDE 29
  • # db/migrate/VERSION_create_line_items.rb
t.decimal :unit_price, null: false t.integer :quantity, null: false, default: 1 # db/migrate/VERSION_create_products.rb t.string :name, null: false t.text :description, null: false t.decimal :price, null: false, default: 0 t.integer :stock, null: false # db/migrate/VERSION_create_carts.rb t.string :status, null: false, default: '' Ruby%on%Rails%%,% 29
slide-30
SLIDE 30

rake dev:setup

rails g task dev fakeup

namespace :dev do desc "Generate fake data" task fakeup: ['db:schema:load', :environment] do 20.times do |i| Product.create( name: "product no.#{i}", description: "description no.#{i}", price: (rand(10) + 1) * 50, stock: rand(91) + 10 ) end cart = Cart.create Product.all.sample(5).each do |product| cart.line_items.create product: product, unit_price: product.price, quantity: rand(4) + 1 end end end Ruby%on%Rails%%,% 30
slide-31
SLIDE 31
  • Cart#total
  • Cart#empty?
  • Cart#clear
  • Order#total
  • LineItem#subtotal
Ruby%on%Rails%%,% 31
slide-32
SLIDE 32

!controller

Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show cart GET /cart(.:format) carts#show rails g controller products index show rails g controller carts show

Ruby%on%Rails%%,% 32
slide-33
SLIDE 33

current_cart

class ApplicationController < ActionController::Base protect_from_forgery with: :exception before_action :set_current_cart, if: ->{ Rails.env.development? } helper_method :current_cart def current_cart @current_cart ||= Cart.find_or_create_by(id: session[:cart_id]) session[:cart_id] = @current_cart.id @current_cart end private def set_current_cart session[:cart_id] = 1 end end Ruby%on%Rails%%,% 33
slide-34
SLIDE 34
Ruby%on%Rails%%,% 34
slide-35
SLIDE 35
  • Ruby%on%Rails%%,%
35
slide-36
SLIDE 36
  • @cart.add_product @product

@product.add_to_cart @cart

  • Ruby%on%Rails%%,%
36
slide-37
SLIDE 37

Rails&

Ruby%on%Rails%%,% 37
slide-38
SLIDE 38

Clean&Architecture&by&Uncle&Bob

Ruby%on%Rails%%,% 38
slide-39
SLIDE 39
  • !LineItem!!CRUD
Ruby%on%Rails%%,% 39
slide-40
SLIDE 40
  • # config/routes.rb
resources :line_items, only: %i[create update destroy] # app/controllers/line_items_controller.rb class LineItemsController < ApplicationController def create @line_item = current_cart.line_items.new line_item_params if @line_item.save redirect_to cart_path, notice: '' else @product = @line_item.product render 'products/show' end end private def line_item_params params.require(:line_item).permit(:quantity, :product_id) end end Ruby%on%Rails%%,% 40
slide-41
SLIDE 41
  • # app/models/line_item.rb
validate :check_stock before_save :set_unit_price def check_stock errors.add(:quantity, 'out of stock') if quantity > product.stock end def set_unit_price self.unit_price = product.price end Ruby%on%Rails%%,% 41
slide-42
SLIDE 42
  • # app/controllers/products_controller.rb
def show @product = Product.find params[:id] @line_item = current_cart.line_items.find_or_initialize_by(product: @product) end <!-- app/views/products/show.html.erb --> <h1><%= @product.name %></h1> <p><%= @product.description %></p> <p><%= @product.price %></p> <p><%= @product.stock %></p> <%= form_for @line_item do |f| %> <%= f.number_field :quantity %> <%= f.hidden_field :product_id %> <%= f.submit '' %> <% end %> Ruby%on%Rails%%,% 42
slide-43
SLIDE 43
  • LineItemsController#destroy
  • LineItemsController#update
Ruby%on%Rails%%,% 43
slide-44
SLIDE 44
  • Ruby%on%Rails%%,%
44
slide-45
SLIDE 45
  • # app/models/cart.rb

accepts_nested_attributes_for :line_items validates_associated :line_items

  • @cart.line_items_attributes = {

0 => {quantity: 10, id: 123}, 1 => {quantity: 10, id: 123} }

Ruby%on%Rails%%,% 45
slide-46
SLIDE 46
  • rails&console
cart = Cart.first cart.line_items_attributes = {0 => {quantity: 10, product_id: __}} # create cart.line_items_attributes = {0 => {id: __, quantity: 10}} # update cart.save Ruby%on%Rails%%,% 46
slide-47
SLIDE 47
  • # config/routes.rb
resource :cart, only: %i[show update] # app/controllers/carts_controller.rb class CartsController < ApplicationController def update if current_cart.update cart_params redirect_to cart_path, notice: '' else render :show end end private def cart_params params.require(:cart).permit(line_items_attributes: [:id, :quantity]) end end Ruby%on%Rails%%,% 47
slide-48
SLIDE 48 <!-- app/views/carts/show.html.erb --> <%= f.fields_for :line_items do |ff| %> <% line_item = ff.object %> <tr> <td><%= link_to line_item.product, line_item.product %></td> <td><%= ff.number_field :quantity %></td> <td></td> </tr> <% end %>
  • <input type="number" name="cart[line_items_attributes][1][quantity]"/>
<input type="hidden" name="cart[line_items_attributes][1][id]"/> Ruby%on%Rails%%,% 48
slide-49
SLIDE 49
  • Ruby%on%Rails%%,%
49
slide-50
SLIDE 50

RubyConf)Taiwan)2014) !Rails! slides/video

Ruby%on%Rails%%,% 50
slide-51
SLIDE 51 Ruby%on%Rails%%,% 51
slide-52
SLIDE 52 Ruby%on%Rails%%,% 52
slide-53
SLIDE 53 # app/models/account.rb class Account < ActiveRecord::Base ... end # app/models/admin/account.rb class Admin::Account < Account ... def transfer_money(account) ... end ... end
  • "Account"Admin::Account"
  • "Admin"
  • Admin::Account""controller"
Ruby%on%Rails%%,% 53
slide-54
SLIDE 54
  • link_to('foo', @post) # href="/posts/:id"

form_for(@post) # action="/posts" or "/posts/:id"

  • link_to('foo', [:admin, @post]) # href="/admin/posts/:id"
link_to('foo', admin_post_path(@post)) # href="/admin/posts/:id" form_for(@post, url: admin_posts_path) # action="/admin/posts" form_for(@post, url: admin_post_path(@post)) # action="/admin/posts/:id" Ruby%on%Rails%%,% 54
slide-55
SLIDE 55
  • !@post!!Admin::Post
link_to('foo', @post) # href="/admin/posts/:id" form_for(@post) # action="/admin/posts/:id" or "/admin/posts" Ruby%on%Rails%%,% 55
slide-56
SLIDE 56
  • !Post!model
  • 1. #config/routes.rb
  • 2. #app/models/admin/post.rb
  • 3. app/controllers/admin/posts_controller.rb
  • 4. app/views/admin/posts/{index,new,edit}.html.erb
Ruby%on%Rails%%,% 56
slide-57
SLIDE 57

scaffold

Ruby%on%Rails%%,% 57
slide-58
SLIDE 58

!scaffold!

  • rails g scaffold Admin::Product name description:text --parent=Product
rails g scaffold Admin::Order name address status --parent=Order
  • lib
└── templates └── erb └── scaffold ├── _form.html.erb ├── edit.html.erb ├── index.html.erb ├── new.html.erb └── show.html.erb Ruby%on%Rails%%,% 58
slide-59
SLIDE 59
  • "lib/templates/erb/scaffold/show.html.erb

"table"

  • "bundle show railtie/lib/rails/generators/erb/

scaffold/templates/show.html.erb

  • Product.stock"
Ruby%on%Rails%%,% 59