Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET /...

59
Ruby on Rails by @tonytonyjan Ruby on Rails , 1

Transcript of Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET /...

Page 1: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

Ruby%on%Rails%�������������

by#@tonytonyjan

Ruby%on%Rails%����%,%���� ��� 1

Page 2: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

��/���/tonytonyjan

• tonytonyjan.net

• Ruby-on-Rails-� ����

• TJDict-Chrome-�����• ���������• �������

• Rails-Girls-Taipei-1~5-���

Ruby%on%Rails%����%,%���� ��� 2

Page 3: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

��

• Ruby&(Rails)

• C&(Qt)

• Java&(Swing)

• Network&Programming

• Informa?on&Retrieval

Ruby%on%Rails%����%,%���� ��� 3

Page 4: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

��

• RubyConf*Brazil*2015*������

• Confoo*Canada*2015*��

• Ruby*Kaigi*Japan*2014*��

• Yahoo*Hack*Taiwan*2013*��

Ruby%on%Rails%����%,%���� ��� 4

Page 5: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

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

Ruby%on%Rails%����%,%���� ��� 5

Page 6: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

�������• ������� ���• �����• �����• ������

Ruby%on%Rails%����%,%���� ��� 6

Page 7: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

�������!gem

Ruby%on%Rails%����%,%���� ��� 7

Page 8: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

User%StoryRuby%on%Rails%����%,%���� ��� 8

Page 9: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

User%Story%*%��• ���• ������• ��������• ��$���!����"• ���� ����� �• ��#�%�

Ruby%on%Rails%����%,%���� ��� 9

Page 10: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

User%Story%*%���• ������• �� ����������• �����������������• ��������������

Ruby%on%Rails%����%,%���� ��� 10

Page 11: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

����• Spree

• ��������

• ror_ecommerce

• ������

• Piggybak

• ����mount�����4carrierwave4����� �

Ruby%on%Rails%����%,%���� ��� 11

Page 12: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

��������

Ruby%on%Rails%����%,%���� ��� 12

Page 13: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

����Ruby%on%Rails%����%,%���� ��� 13

Page 14: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

����• ����"#>"/products

• ����"#>"/products/:id

• ����"#>"/cart

• ����"#>"/orders/new

• ���"#>"/orders/:id

• �����"#>"/admin/*

Ruby%on%Rails%����%,%���� ��� 14

Page 15: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

����git clone https://github.com/tonytonyjan/my_cartcd my_cartrails s

Ruby%on%Rails%����%,%���� ��� 15

Page 16: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

����������

$ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#indexproduct GET /products/:id(.:format) products#show cart GET /cart(.:format) carts#show

Ruby%on%Rails%����%,%���� ��� 16

Page 17: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

# config/routes.rbroot 'products#index'resources :products, only: :showresource :cart, only: :show

Ruby%on%Rails%����%,%���� ��� 17

Page 18: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

�����ERD�

Ruby%on%Rails%����%,%���� ��� 18

Page 19: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

�����ERD�

Ruby%on%Rails%����%,%���� ��� 19

Page 20: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

��������1.���

2.��������

3.��

Ruby%on%Rails%����%,%���� ��� 20

Page 21: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

Ruby%on%Rails%����%,%���� ��� 21

Page 22: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

���

��������Ruby%on%Rails%����%,%���� ��� 22

Page 23: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

Ruby%on%Rails%����%,%���� ��� 23

Page 24: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

�����

Ruby%on%Rails%����%,%���� ��� 24

Page 25: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

Ruby%on%Rails%����%,%���� ��� 25

Page 26: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

�������• Agile'Web'Development'with'Rails'������

• ror_ecommerce'���

• Spree�Piggybak'��'Cart'en>ty���'Order'��� ��

Ruby%on%Rails%����%,%���� ��� 26

Page 27: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

���rails g model product name description:text price:decimal stock:integerrails g model order name address status payment_methodrails g model cartrails g model line_item \order:references cart:references product:references \unit_price:decimal quantity:integer

Ruby%on%Rails%����%,%���� ��� 27

Page 28: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

����# app/models/cart.rbclass Cart has_many :line_itemsend

# app/models/product.rbclass Product has_many :line_itemsend

# app/models/order.rbclass Order has_many :line_items has_many :products, through: :line_itemsend

Ruby%on%Rails%����%,%���� ��� 28

Page 29: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

��������# db/migrate/VERSION_create_line_items.rbt.decimal :unit_price, null: falset.integer :quantity, null: false, default: 1

# db/migrate/VERSION_create_products.rbt.string :name, null: falset.text :description, null: falset.decimal :price, null: false, default: 0t.integer :stock, null: false

# db/migrate/VERSION_create_carts.rbt.string :status, null: false, default: '���'

Ruby%on%Rails%����%,%���� ��� 29

Page 30: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

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 endend

Ruby%on%Rails%����%,%���� ��� 30

Page 31: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

���������

• Cart#total

• Cart#empty?

• Cart#clear

• Order#total

• LineItem#subtotal

Ruby%on%Rails%����%,%���� ��� 31

Page 32: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

��!controller

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

rails g controller products index showrails g controller carts show

Ruby%on%Rails%����%,%���� ��� 32

Page 33: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

current_cartclass 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

Page 34: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

��• �����• ����• ���

Ruby%on%Rails%����%,%���� ��� 34

Page 35: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

�����Ruby%on%Rails%����%,%���� ��� 35

Page 36: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

���@cart.add_product @[email protected]_to_cart @cart

������

Ruby%on%Rails%����%,%���� ��� 36

Page 37: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

Rails&�� ����������

Ruby%on%Rails%����%,%���� ��� 37

Page 38: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

Clean&Architecture&by&Uncle&Bob

Ruby%on%Rails%����%,%���� ��� 38

Page 39: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

��� ��������������!LineItem!�!CRUD

Ruby%on%Rails%����%,%���� ��� 39

Page 40: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

��������# config/routes.rbresources :line_items, only: %i[create update destroy]

# app/controllers/line_items_controller.rbclass 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) endend

Ruby%on%Rails%����%,%���� ��� 40

Page 41: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

��������# app/models/line_item.rbvalidate :check_stockbefore_save :set_unit_price

def check_stock errors.add(:quantity, 'out of stock') if quantity > product.stockend

def set_unit_price self.unit_price = product.priceend

Ruby%on%Rails%����%,%���� ��� 41

Page 42: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

����# app/controllers/products_controller.rbdef 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

Page 43: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

��• LineItemsController#destroy

• LineItemsController#update

Ruby%on%Rails%����%,%���� ��� 43

Page 44: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

�����Ruby%on%Rails%����%,%���� ��� 44

Page 45: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

������# app/models/cart.rbaccepts_nested_attributes_for :line_itemsvalidates_associated :line_items

�������� ���

@cart.line_items_attributes = { 0 => {quantity: 10, id: 123}, 1 => {quantity: 10, id: 123}}

Ruby%on%Rails%����%,%���� ��� 45

Page 46: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

��rails&console

cart = Cart.firstcart.line_items_attributes = {0 => {quantity: 10, product_id: __}} # createcart.line_items_attributes = {0 => {id: __, quantity: 10}} # updatecart.save

Ruby%on%Rails%����%,%���� ��� 46

Page 47: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

�������# config/routes.rbresource :cart, only: %i[show update]

# app/controllers/carts_controller.rbclass 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]) endend

Ruby%on%Rails%����%,%���� ��� 47

Page 48: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

<!-- 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

Page 49: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

����Ruby%on%Rails%����%,%���� ��� 49

Page 50: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

RubyConf)Taiwan)2014)�������!Rails!��

slides/video

Ruby%on%Rails%����%,%���� ��� 50

Page 51: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

Ruby%on%Rails%����%,%���� ��� 51

Page 52: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

Ruby%on%Rails%����%,%���� ��� 52

Page 53: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

# app/models/account.rbclass Account < ActiveRecord::Base ...end

# app/models/admin/account.rbclass Admin::Account < Account ... def transfer_money(account) ... end ...end

• ��"Account"������Admin::Account"���

• ��������"Admin"�����

• Admin::Account"�� ��"controller"��Ruby%on%Rails%����%,%���� ��� 53

Page 54: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

�������

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

Page 55: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

��������!@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

Page 56: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

�����������!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

Page 57: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

scaffoldRuby%on%Rails%����%,%���� ��� 57

Page 58: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

��!scaffold!�������rails g scaffold Admin::Product name description:text --parent=Productrails 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

Page 59: Ruby%on%Rails%2015/05/04  · $ bin/rake routes Prefix Verb URI Pattern Controller#Action root GET / products#index product GET /products/:id(.:format) products#show rails g model

����• � �'• ��!"�&���'

• ��"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