over 2 years ago

重點1:怎麼使用application_helper.rb,在application_helper.rb弄的method,可以用到view裡面去。
重點2:這個的用法也很重要:<% provide(:title, "Home") %>
參考:method / block / yield / Proc / lambda 全面解釋
參考:yield and provide() inside template

provide是放在<% %>,所以不會顯示出來。
provide stores a block of markup in an identifier for later use. In this case, 'Help' in the symbol :title. The provide is enclosed in <% %> to indicate it is executing this code and not printing out in the view.
yield是放在<%= %>,所以會顯示出來。
yield in this case just spits that block back out. The yield is enclosed in <%= %> to indicate it is being printed out into the view.
Think of it as setting a variable and printing out a variable.
See: content_for 和provide for more information. Note that provide is really a wrapper for content_for so that's where the good stuff is in that link.

重點3:ifunless 分不清楚

  1. This uses the built-in Rails function stylesheet_link_tag (which you can read more about at the Rails API) to include application.css for all media types (including computer screens and printers).
    stylesheet_link_tag 後面的application指的是application.css

    app/views/layouts/application.html.erb
     <!DOCTYPE html>
    <html>
    <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
    <%= stylesheet_link_tag    'application', media: 'all',
                                              'data-turbolinks-track' => true %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
    <%= csrf_meta_tags %>
    </head>
    <body>
    <%= yield %>
    </body>
    </html>
    
    <%= stylesheet_link_tag 'application', media: 'all',
                                       'data-turbolinks-track' => true %>
    
  2. 一步一步的做調整:(這邊的重點應該是在於怎麼使用application_helper.rb,在application_helper.rb弄的method,可以用到view裡面去。)

    <%= yield(:title) %> | Ruby on Rails Tutorial Sample App
    

    這兩個會相呼應。

    <% provide(:title, "Home") %>
    <h1>Sample App</h1>
    <p>
    This is the home page for the
    <a href="http://www.railstutorial.org/">Ruby on Rails Tutorial</a>
    sample application.
    </p>
    

    在application_helper.rb裡面,寫一個新的method。
    we’ll define a custom helper called full_title. The full_title helper returns a base title, “Ruby on Rails Tutorial Sample App”, if no page title is defined, and adds a vertical bar preceded by the page title if one is defined (Listing 4.2).1

    app/helpers/application_helper.rb
    module ApplicationHelper
    # Returns the full title on a per-page basis.
    
    def full_title(page_title = '')
        base_title = "Ruby on Rails Tutorial Sample App"
            if page_title.empty?
                base_title
            else
                page_title + " | " + base_title
            end
        end
    end
    
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
    

    上面就可以改成下面這樣:

    <title><%= full_title(yield(:title)) %></title>
    

    然後把它加到application.html.erb裡面去

    app/views/layouts/application.html.erb
     <!DOCTYPE html>
    <html>
    <head>
    <title><%= full_title(yield(:title)) %></title>
    <%= stylesheet_link_tag    'application', media: 'all',
                                              'data-turbolinks-track' => true %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
    <%= csrf_meta_tags %>
    </head>
    <body>
    <%= yield %>
    </body>
    </html>
    

    接著要把home.html.erb裡面的<% provide(:title, "Home") %>拿掉????

    app/views/static_pages/home.html.erb
     <% provide(:title, "Home") %>
    <h1>Sample App</h1>
    <p>
    This is the home page for the
    <a href="http://www.railstutorial.org/">Ruby on Rails Tutorial</a>
    sample application.
    </p>
    

    這邊有點怪怪的,好像把<% provide(:title, "Home") %>拿掉,只是為了要測試能不能出現base_title = "Ruby on Rails Tutorial Sample App",如果真的上線,應該還是要把<% provide(:title, "Home") %>留著。

    app/views/static_pages/home.html.erb
     <h1>Sample App</h1>
    <p>
    This is the home page for the
    <a href="http://www.railstutorial.org/">Ruby on Rails Tutorial</a>
    sample application.
    </p>
    
  3. 作者覺得 interpolation的方法比較好

    Concatenation, with a space in between
    first_name + " " + last_name 
    => "Michael Hartl"
    
    The equivalent interpolation
    >> "#{first_name} #{last_name}"
    => "Michael Hartl"
    
  4. put會多一行,print不會。print加上\n就會有跟puts一樣的多一行的效果。

    >> puts "foo"     # put string
    
    foo
    => nil
    >> print "foo"    # print string (same as puts, but without the newline)
    
    foo=> nil
    >> print "foo\n"  # Same as puts "foo"
    
    foo
    => nil
    
  5. Single-quoted strings don't allow interpolation,所以要用雙引號比較好""

    '#{foo} bar'     
    => "\#{foo} bar"
    
  6. Single-quoted strings:這邊看不懂

    >> 'foo'          # A single-quoted string
    
    => "foo"
    >> 'foo' + 'bar'
    => "foobar"
    
    >> '#{foo} bar'     # Single-quoted strings don't allow interpolation
    
    => "\#{foo} bar"
    
    >> '\n'       # A literal 'backslash n' combination
    
    => "\\n"
    
    >> 'Newlines (\n) and tabs (\t) both use the backslash character \.'
    => "Newlines (\\n) and tabs (\\t) both use the backslash character \\."
    
  7. 問號(?)是用在測試boolean: true or false的,對於流程控制特別有用。
    Note the question mark at the end of the empty? method. This is a Ruby convention indicating that the return value is boolean: true or false. Booleans are especially useful for control flow else + if

  8. 超過一個子句,就可以用 elsif (else + if)

    >> if s.nil?
    >>   "The variable is nil"
    >> elsif s.empty?
    >>   "The string is empty"
    >> elsif s.include?("foo")
    >>   "The string includes 'foo'"
    >> end
    => "The string includes 'foo'"
    
  9. to_s method that can convert virtually any object to a string

    >> nil.empty?
    NoMethodError: undefined method `empty?' for nil:NilClass
    >> nil.to_s.empty?      # Message chaining
    => true
    
  10. The code also shows an alternate use of the if keyword: Ruby allows you to write a statement that is evaluated only if the statement following if is true. There’s a complementary unless keyword that works the same way:

    puts "x is not empty" if !x.empty?
    
    >> string = "foobar"
    >> puts "The string '#{string}' is nonempty." unless string.empty?
    The string 'foobar' is nonempty.
    => nil
    
  11. It’s worth noting that the nil object is special, in that it is the only Ruby object that is false in a boolean context, apart from false itself. We can see this using !! (read “bang bang”), which negates an object twice, thereby coercing it to its boolean value:

    >> !!nil
    => false
    

    In particular, all other Ruby objects are true, even 0:

    >> !!0
    => true
    
  12. module ApplicationHelper: modules give us a way to package together related methods, which can then be mixed in to Ruby classes using include. When writing ordinary Ruby, you often write modules and include them explicitly yourself, but in the case of a helper module Rails handles the inclusion for us. The result is that the full_title method is automagically available in all our views.

    include module
    
  13. Arrays and ranges
    Array裡面的東西是有順序的,Hash裡面的東西沒有順序
    An array is just a list of elements in a particular order.

  14. split method:可以把string變成array

    >>  "foo bar     baz".split     # Split a string into a three-element array.
    
    => ["foo", "bar", "baz"]
    

    split('x'):按照()裡面的東西去拆分string,然後變成array

    >> "fooxbarxbazx".split('x')
    => ["foo", "bar", "baz"]
    
  15. Array 第一個元素的index是0,最後一個是-1:

    >> a = [42, 8, 17]
    => [42, 8, 17]
    >> a[0]               # Ruby uses square brackets for array access.
    
    => 42
    >> a[1]
    => 8
    >> a[2]
    => 17
    >> a[-1]              # Indices can even be negative!
    
    => 17
    
    >> a                  # Just a reminder of what 'a' is
    
    => [42, 8, 17]
    >> a.first
    => 42
    >> a.second
    => 8
    >> a.last
    => 17
    >> a.last == a[-1]    # Comparison using ==
    
    => true
    
  16. ==等於 , !=(“not equal”)不等於

    >> x = a.length       # Like strings, arrays respond to the 'length' method.
    
    => 3
    >> x == 3
    => true
    >> x == 1
    => false
    >> x != 1
    => true
    >> x >= 1
    => true
    >> x < 1
    => false
    
  17. emptyincludesortreverseshuffle:

    >> a
    => [42, 8, 17]
    >> a.empty?
    => false
    >> a.include?(42)
    => true
    >> a.sort
    => [8, 17, 42]
    >> a.reverse
    => [17, 8, 42]
    >> a.shuffle
    => [17, 42, 8]
    >> a
    => [42, 8, 17]
    
  18. 驚嘆號(!)可以把array的改變儲存起來:

    >> a
    => [42, 8, 17]
    >> a.sort!
    => [8, 17, 42]
    >> a
    => [8, 17, 42]
    
  19. push method<<:都可以把新東西加到array裡面去
    push method or its equivalent operator, <<

    >> a.push(6)                  # Pushing 6 onto an array
    
    => [42, 8, 17, 6]
    >> a << 7                     # Pushing 7 onto an array
    
    => [42, 8, 17, 6, 7]
    >> a << "foo" << "bar"        # Chaining array pushes
    
    => [42, 8, 17, 6, 7, "foo", "bar"]
    
  20. Ruby可以把integers 和 strings 合在一起:join
    join method 把array裡面的東西合成一個string:

    >> a
    => [42, 8, 17, 6, 7, "foo", "bar"]
    >> a.join                       # Join on nothing.
    
    => "4281767foobar"
    >> a.join(', ')                 # Join on comma-space.
    
    => "42, 8, 17, 6, 7, foo, bar"
    
  21. Range如果要改成array(to_a),要記得先用括號把range括起來:

    >> 0..9
    => 0..9
    >> 0..9.to_a              # Oops, call to_a on 9.
    
    NoMethodError: undefined method `to_a' for 9:Fixnum
    >> (0..9).to_a            # Use parentheses to call to_a on the range.
    => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
  22. Range來把array裡面的東西叫出來:
    %w是用來建一個文字array的:

    >> a = %w[foo bar baz quux]         # Use %w to make a string array.
    
    => ["foo", "bar", "baz", "quux"]
    >> a[0..2]
    => ["foo", "bar", "baz"]
    
  23. 不用特別去數array內有幾個元素,直接用index -1 就可以從頭掃到尾:

    >> a = (0..9).to_a
    => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >> a[2..(a.length-1)]               # Explicitly use the array's length.
    
    => [2, 3, 4, 5, 6, 7, 8, 9]
    >> a[2..-1]                         # Use the index -1 trick.
    
    => [2, 3, 4, 5, 6, 7, 8, 9]
    
  24. Range也可以用在文字上

    >> ('a'..'e').to_a
    => ["a", "b", "c", "d", "e"]
    
  25. 開始講BLOCK: ArrayRange的一些method都可以用block
    Both arrays and ranges respond to a host of methods that accept blocks
    譬如range (1..5)可以用 block { |i| puts 2 * i }

    >> (1..5).each { |i| puts 2 * i }
    2
    4
    6
    8
    10
    => 1..5
    
  26. block { |i| puts 2 * i }相等於下面這個:

    >> (1..5).each do |i|
    ?>   puts 2 * i
    >> end
    2
    4
    6
    8
    10
    => 1..5
    
  27. using curly braces only for short one-line blocks
    the do..end syntax for longer one-liners and for multi-line blocks:

    >> (1..5).each do |number|
    ?>   puts 2 * number
    >>   puts '--'
    >> end
    2
    --
    4
    --
    6
    --
    8
    --
    10
    --
    => 1..5
    
  28. 更多範例

    >> 3.times { puts "Betelgeuse!" }   # 3.times takes a block with no variables.
    
    "Betelgeuse!"
    "Betelgeuse!"
    "Betelgeuse!"
    => 3
    
    >> (1..5).map { |i| i**2 }          # The ** notation is for 'power'.
    
    => [1, 4, 9, 16, 25]
    
  29. %w是把array裡面的東西轉成string

    >> %w[a b c]                        # Recall that %w makes string arrays.
    
    => ["a", "b", "c"]
    
  30. map method returns the result of applying the given block to each element in the array or range.
    參考:map可以來產生出一個array: 常見 block 說明和應用:do, map, collect

    >> %w[a b c].map { |char| char.upcase }
    => ["A", "B", "C"]
    
    >> %w[A B C].map { |char| char.downcase }
    => ["a", "b", "c"]
    

    &:是個縮寫。 we’ll discuss in Section 4.3.3.

    >> %w[A B C].map { |char| char.downcase }
    => ["a", "b", "c"]
    >> %w[A B C].map(&:downcase)
    => ["a", "b", "c"]
    
  31. 這個其實也是block:

    test "should get home" do
    get :home
    assert_response :success
    assert_select "title", "Ruby on Rails Tutorial Sample App"
    end
    
  32. 之前的例子

    ('a'..'z').to_a.shuffle[0..7].join
    >> ('a'..'z').to_a                     # An alphabet array
    
    => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
    "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
    >> ('a'..'z').to_a.shuffle             # Shuffle it.
    
    => ["c", "g", "l", "k", "h", "z", "s", "i", "n", "d", "y", "u", "t", "j", "q",
    "b", "r", "o", "f", "e", "w", "v", "m", "a", "x", "p"]
    >> ('a'..'z').to_a.shuffle[0..7]       # Pull out the first eight elements.
    
    => ["f", "w", "i", "a", "h", "p", "c", "x"]
    >> ('a'..'z').to_a.shuffle[0..7].join  # Join them together to make one string.
    
    => "mznpybuj"
    
  33. Hash沒有順序,只有keyvalue。如果需要有順序上的差別,記得用array:

    >> user = {}                          # {} is an empty hash.
    
    => {}
    >> user["first_name"] = "Michael"     # Key "first_name", value "Michael"
    
    => "Michael"
    >> user["last_name"] = "Hartl"        # Key "last_name", value "Hartl"
    
    => "Hartl"
    >> user["first_name"]                 # Element access is like arrays.
    
    => "Michael"
    >> user                               # A literal representation of the hash
    
    => {"last_name"=>"Hartl", "first_name"=>"Michael"}
    
  34. 舊的用法:=> called a “hashrocket”:

    >> user = { "first_name" => "Michael", "last_name" => "Hartl" }
    => {"last_name"=>"Hartl", "first_name"=>"Michael"}
    
  35. 用symbol比用string當key好。

    >> "name".split('')
    => ["n", "a", "m", "e"]
    >> :name.split('')
    NoMethodError: undefined method `split' for :name:Symbol
    >> "foobar".reverse
    => "raboof"
    >> :foobar.reverse
    NoMethodError: undefined method `reverse' for :foobar:Symbol
    
  36. Symbols不能有-,也不能用數字作為開頭。

    >> :foo-bar
    NameError: undefined local variable or method `bar' for main:Object
    >> :2foo
    SyntaxError
    
  37. hash裡面沒有的key,會回傳nil

    >> user = { :name => "Michael Hartl", :email => "michael@example.com" }
    => {:name=>"Michael Hartl", :email=>"michael@example.com"}
    >> user[:name]              # Access the value corresponding to :name.
    
    => "Michael Hartl"
    >> user[:password]          # Access the value of an undefined key.
    
    => nil
    
  38. :取代=>,這樣跟javascript比較相似

    >> h1 = { :name => "Michael Hartl", :email => "michael@example.com" }
    => {:name=>"Michael Hartl", :email=>"michael@example.com"}
    >> h2 = { name: "Michael Hartl", email: "michael@example.com" }
    => {:name=>"Michael Hartl", :email=>"michael@example.com"}
    >> h1 == h2
    => true
    
    { name: "Michael Hartl", email: "michael@example.com" }
    
    { :name => "Michael Hartl" }
    

    這兩個其實是一樣的

    { name: "Michael Hartl" }
    
  39. hashes-of-hashes / Nested hashes:Hash裡面還有Hash

    >> params = {}        # Define a hash called 'params' (short for 'parameters').
    
    => {}
    >> params[:user] = { name: "Michael Hartl", email: "mhartl@example.com" }
    => {:name=>"Michael Hartl", :email=>"mhartl@example.com"}
    >> params
    => {:user=>{:name=>"Michael Hartl", :email=>"mhartl@example.com"}}
    >>  params[:user][:email]
    => "mhartl@example.com"
    
  40. Hash也可以用each,不過hash會去抓a key and a value

    >> flash = { success: "It worked!", danger: "It failed." }
    => {:success=>"It worked!", :danger=>"It failed."}
    >> flash.each do |key, value|
    ?>   puts "Key #{key.inspect} has value #{value.inspect}"
    >> end
    Key :success has value "It worked!"
    Key :danger has value "It failed."
    
  41. inspect method, which returns a string with a literal representation of the object it’s called on:回傳strinf,會連"":都顯示出來

    >> puts (1..5).to_a            # Put an array as a string.
    
    1
    2
    3
    4
    5
    >> puts (1..5).to_a.inspect    # Put a literal array.
    
    [1, 2, 3, 4, 5]
    >> puts :name, :name.inspect
    name
    :name
    >> puts "It worked!", "It worked!".inspect
    It worked!
    "It worked!"
    

    inspect 可以用p來代替

    >> p :name             # Same output as 'puts :name.inspect'
    
    :name
    
  42. 重新看一次CSS:

    <%= stylesheet_link_tag 'application', media: 'all',
    'data-turbolinks-track' => true %>
    
    stylesheet_link_tag 'application', media: 'all',
    'data-turbolinks-track' => true
    
  43. parentheses are optional, so these two are equivalent:

    stylesheet_link_tag('application', media: 'all',
                                   'data-turbolinks-track' => true)
    
    stylesheet_link_tag 'application', media: 'all',
                                   'data-turbolinks-track' => true
    
  44. hashes 是最後一個變數的時候,可以省略:

    stylesheet_link_tag 'application', { media: 'all',
                                     'data-turbolinks-track' => true }
    
    stylesheet_link_tag 'application', media: 'all',
                                   'data-turbolinks-track' => true
    
  45. 'data-turbolinks-track' => true 還是用舊的寫法,主要是因為-不能用在symbol裡:

    'data-turbolinks-track' => true
    
  46. 這樣的斷行方式比較好閱讀,一行最好是少於80的字母。

    stylesheet_link_tag 'application', media: 'all',
                                   'data-turbolinks-track' => true
    
    stylesheet_link_tag 'application', media: 'all',
                                   'data-turbolinks-track' => true
    
  47. Because of the <%= %> brackets, the results are inserted into the template by ERb, and if you view the source of the page in your browser you should see the HTML needed to include a stylesheet (Listing 4.11).

    <link data-turbolinks-track="true" href="/assets/application.css" media="all"
    rel="stylesheet" />
    
  48. 開始講classes

  49. String的做法:

    >> s = "foobar"       # A literal constructor for strings using double quotes
    
    => "foobar"
    >> s.class
    => String
    
    >> s = String.new("foobar")   # A named constructor for a string
    
    => "foobar"
    >> s.class
    => String
    >> s == "foobar"
    => true
    
  50. Arrays的做法:

    >> a = Array.new([1, 3, 2])
    => [1, 3, 2]
    
  51. Hashes的做法:可以定義不存在的key的value - 在new的時候先給予值

    >> h = Hash.new
    => {}
    >> h[:foo]            # Try to access the value for the nonexistent key :foo.
    
    => nil
    >> h = Hash.new(0)    # Arrange for nonexistent keys to return 0 instead of nil.
    
    => {}
    >> h[:foo]
    => 0
    
  52. 可以用在Class的method = class method
    Class new 出來的東西,叫做instance of the class
    instance of the class的method = instance method
    When a method gets called on the class itself, as in the case of new, it’s called a class method. The result of calling new on a class is an object of that class, also called an instance of the class. A method called on an instance, such as length, is called an instance method.

  53. 講superclass method:

    >> s = String.new("foobar")
    => "foobar"
    >> s.class                        # Find the class of s.
    
    => String
    >> s.class.superclass             # Find the superclass of String.
    
    => Object
    >> s.class.superclass.superclass  # Ruby 1.9 uses a new BasicObject base class
    
    => BasicObject
    >> s.class.superclass.superclass.superclass
    => nil
    

  54. 自己弄一個word的class來試看看
    Let’s make a Word class with a palindrome? method that returns true if the word is the same spelled forward and backward:

    >> class Word
    >>   def palindrome?(string)
    >>     string == string.reverse
    >>   end
    >> end
    => :palindrome?
    

    We can use it as follows:

    >> w = Word.new              # Make a new Word object.
    
    => #<Word:0x22d0b20>
    
    >> w.palindrome?("foobar")
    => false
    >> w.palindrome?("level")
    => true
    
  55. Since a word is a string, it’s more natural to have our Word class inherit from String, as seen in Listing 4.12.

    >> class Word < String             # Word inherits from String.
    
    >>   # Returns true if the string is its own reverse.
    
    >>   def palindrome?
    >>     self == self.reverse        # self is the string itself.
    
    >>   end
    >> end
    => nil
    
  56. Word < String is the Ruby syntax for inheritance

    >> s = Word.new("level")    # Make a new Word, initialized with "level".
    
    => "level"
    >> s.palindrome?            # Words have the palindrome? method.
    
    => true
    >> s.length                 # Words also inherit all the normal string methods.
    
    => 5
    
    >> s.class
    => Word
    >> s.class.superclass
    => String
    >> s.class.superclass.superclass
    => Object
    

  57. self: word is its own reverse involves accessing the word inside the Word class. Ruby allows us to do this using the self keyword: inside the Word class, self is the object itself, which means we can use

    self == self.reverse
    
  58. inside the String class the use of self. is optional on a method or attribute (unless we’re making an assignment), sow ould work as well.

    self == reverse
    
  59. 在Ruby,我們可以自己修改既有的class裡面的method

    >> "level".palindrome?
    NoMethodError: undefined method `palindrome?' for "level":String
    
    >> class String
    >>   # Returns true if the string is its own reverse.
    
    >>   def palindrome?
    >>     self == self.reverse
    >>   end
    >> end
    => nil
    >> "deified".palindrome?
    => true
    
  60. blank 跟 empty是不一樣的

    >> "".blank?
    => true
    >> "      ".empty?
    => false
    >> "      ".blank?
    => true
    >> nil.blank?
    => true
    
  61. Note also that nil is blank; since nil isn’t a string, this is a hint that Rails actually adds blank? to String’s base class, which (as we saw at the beginning of this section) is Object itself.

  62. A controller class

    class StaticPagesController < ApplicationController
    def home
    end
    def help
    end
    def about
    end
    end
    
  63. StaticPagesController is a class that inherits from ApplicationController, and comes equipped with home, help, and about methods

    >> controller = StaticPagesController.new
    => #<StaticPagesController:0x22855d0>
    
    >> controller.class
    => StaticPagesController
    >> controller.class.superclass
    => ApplicationController
    >> controller.class.superclass.superclass
    => ActionController::Base
    >> controller.class.superclass.superclass.superclass
    => ActionController::Metal
    >> controller.class.superclass.superclass.superclass.superclass
    => AbstractController::Base
    >> controller.class.superclass.superclass.superclass.superclass.superclass
    => Object
    

  64. 因為home method裡面我們沒有寫東西,所以是nil。
    Here the return value is nil because the home action is blank.

    >> controller.home
    => nil
    

    But wait—actions don’t have return values, at least not ones that matter. The point of the home action, as we saw in Chapter 3, is to render a web page, not to return a value. And I sure don’t remember ever calling StaticPagesController.new anywhere. What’s going on?
    What’s going on is that Rails is written in Ruby, but Rails isn’t Ruby. Some Rails classes are used like ordinary Ruby objects, but some are just grist for Rails’ magic mill. Rails is sui generis, and should be studied and understood separately from Ruby.

  65. 用example_user.rb取代console去產生user

    example_user.rb
    class User
        attr_accessor :name, :email
        def initialize(attributes = {})
            @name  = attributes[:name]
            @email = attributes[:email]
        end
        def formatted_email
            "#{@name} <#{@email}>"
        end
    end
    
  66. attr_accessor :name, :email
    透過 instance variables(@name@email)可以存取(“getter” 和 “setter”)用戶的nameemail
    instance variables可以直接用在view裡面
    creates attribute accessors corresponding to a user’s name and email address. This creates “getter” and “setter” methods that allow us to retrieve (get) and assign (set) @name and @email instance variables.
    In Rails, the principal importance of instance variables is that they are automatically available in the views, but in general they are used for variables that need to be available throughout a Ruby class. (We’ll have more to say about this in a moment.) Instance variables always begin with an @ sign, and are nil when undefined.
    initialize就是new的意思:

    def initialize(attributes = {})
        @name  = attributes[:name]
        @email = attributes[:email]
    end
    

    initialize(attributes = {})預設值是一個空的hash,因此用戶可以不用輸入name跟email
    4.3.3:如果key不存在,Hash會回傳nil。(看下面的例子)
    Here the attributes variable has a default value equal to the empty hash, so that we can define a user with no name or email address. (Recall from Section 4.3.3 that hashes return nil for nonexistent keys, so attributes[:name] will be nil if there is no :name key, and similarly for attributes[:email].)

    def formatted_email
        "#{@name} <#{@email}>"
    end
    
    >> require './example_user'     # This is how you load the example_user code.
    
    => true
    >> example = User.new
    => #<User:0x224ceec @email=nil, @name=nil>
    
    >> example.name                 # nil since attributes[:name] is nil
    
    => nil
    >> example.name = "Example User"           # Assign a non-nil name
    
    => "Example User"
    >> example.email = "user@example.com"      # and a non-nil email address
    
    => "user@example.com"
    >> example.formatted_email
    => "Example User <user@example.com>"
    

    example.name = "Example User"
    將@name設定為"Example User"

    >> user = User.new(name: "Michael Hartl", email: "mhartl@example.com")
    => #<User:0x225167c @email="mhartl@example.com", @name="Michael Hartl">
    
    >> user.formatted_email
    => "Michael Hartl <mhartl@example.com>"
    
 
over 2 years ago

備註1:上傳Heroku的時候會遇到一些warning,作者建議看 Section 7.5
重點2:Box 3.1. Undoing things:不小心做錯了怎麼辦?
有兩個方法:generate vs destroydb:migrate vs db:rollback,還有db:migrate VERSION=0
$ rails generate controller StaticPages home help
$ rails destroy controller StaticPages home help
$ rails generate model User name:string email:string
$ rails destroy model User
$ bundle exec rake db:migrate
$ bundle exec rake db:rollback
$ bundle exec rake db:migrate VERSION=0
重點3: 教簡單的test方法:改變title,還有簡單的refactor,refactor之後,要記得再測試一次。
備註4: Test-driven development uses a “Red, Green, Refactor” cycle.
備註5: embedded Ruby, also called ERb.
重點6:如何使用<% provide(:title, "Home")%>
重點7:講到application.html.erb

  1. update the gems
    $ bundle update

  2. flags for “all changes” (-a) and a message (-m).
    Git also lets us roll the two flags into one using git commit -am "Message".
    $ git commit -am "Improve the README"
    Section 3.1都是準備工作:

  3. 建一個新的repo,然後上傳。
    create a new repository at Bitbucket
    $ git remote add origin git@bitbucket.org:<username>/sample_app.git
    $ git push -u origin --all # pushes up the repo and its refs for the first time

  4. commit之後,再新增一個Heroku,然後再上傳
    $ git commit -am "Add hello"
    $ heroku create
    $ git push heroku master

  5. If you run into problems at Heroku, make sure to take a look at the production logs to try to diagnose the problem:
    $ heroku logs
    Heroku的網站上面也可以看到

  6. 可能會做大幅度的修改時,記得先弄一個新的branch出來。
    Recall from Section 1.4.4 that, when using Git, it’s a good practice to do our work on a separate topic branch rather than the master branch. If you’re using Git for version control, you should run the following command to checkout a topic branch for static pages:
    $ git checkout master
    $ git checkout -b static-pages
    (The first line here is just to make sure that you start on the master branch, so that the static-pages topic branch is based on master. You can skip that command if you’re already on the master branch.)
    checkout -b可以同時新增跟轉換到新的branch

  7. Controller的名字要用駱駝:StaticPages。後面是action,可以直接用小寫。
    $ rails generate controller StaticPages home help
    附註:這樣會同時產生一些相關連的檔案,不過controller裡面只會有home跟help這兩個actions,其他像是standard REST actions中的index、show、new、edit、create、update、destroy都不會有。
    而且還會自動去修改routes.rb
    routes.rb會多出來兩個,defines the correspondence between URLs and web pages
    如果後面沒有接action,可能就變成resource::staticpages

    Rails.application.routes.draw do
    get 'static_pages/home'
    get 'static_pages/help'
    end
    
  8. commit 新的 branch
    $ git push -u origin static-pages
    之後可以用git push

  9. StaticPages 跟 static_pages ,其實產生的controller都會是static_pages_controller.rb

  10. Box 3.1. Undoing things:不小心做錯了怎麼辦?
    $ rails generate controller StaticPages home help
    $ rails destroy controller StaticPages home help
    $ rails generate model User name:string email:string
    $ rails destroy model User
    $ bundle exec rake db:migrate
    $ bundle exec rake db:rollback
    $ bundle exec rake db:migrate VERSION=0
    從0開始,where the version numbers come from listing the migrations sequentially.

  11. POST is the request sent by your browser when you submit a form.
    POST requests are typically used for creating things

  12. There is an especially lively debate over the use of test-driven development (TDD),6 a testing technique in which the programmer writes failing tests first, and then writes the application code to get the tests to pass.
    TDD:先做錯的,然後再把它改正。

  13. rails generate controller會自動幫我們產生一個測試檔 (a test file):
    assert_response

    $ ls test/controllers/
    static_pages_controller_test.rb
    
    test/controllers/static_pages_controller_test.rb
    require 'test_helper'
    
    class StaticPagesControllerTest < ActionController::TestCase
    
      test "should get home" do
    get :home
    assert_response :success
    end
    
      test "should get help" do
    get :help
    assert_response :success
    end
    end
    
  14. rake test來執行test

    $ bundle exec rake test
    2 tests, 2 assertions, 0 failures, 0 errors, 0 skips
    
  15. rake test來執行test,如果有錯誤,就會出現錯誤訊息:
    這邊的例子是先出現routing錯誤,又出現action錯誤,然後才是view錯誤

    $ bundle exec rake test
    ActionController::UrlGenerationError:
    No route matches {:action=>"about", :controller=>"static_pages"}
    
    $ bundle exec rake test
    AbstractController::ActionNotFound:
    The action 'about' could not be found for StaticPagesController
    
    $ bundle exec rake test
    ActionView::MissingTemplate: Missing template static_pages/about
    
  16. 測試title:assert_select

    test/controllers/static_pages_controller_test.rb
     require 'test_helper'
    
    class StaticPagesControllerTest < ActionController::TestCase
    
    test "should get home" do
    get :home
    assert_response :success
    assert_select "title", "Home | Ruby on Rails Tutorial Sample App"
    end
    
    test "should get help" do
    get :help
    assert_response :success
    assert_select "title", "Help | Ruby on Rails Tutorial Sample App"
    end
    
    test "should get about" do
    get :about
    assert_response :success
    assert_select "title", "About | Ruby on Rails Tutorial Sample App"
    end
    
  17. 測試結果會是錯誤

    $ bundle exec rake test
    3 tests, 6 assertions, 3 failures, 0 errors, 0 skips
    

    <title>Home | Ruby on Rails Tutorial Sample App</title>一個一個加到HTML之後,就會正確了。

  18. <% provide(:title, "Home") %><title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
    這個時候,$ bundle exec rake test還是會是正確的。

    app/views/static_pages/home.html.erb
     <% provide(:title, "Home") %>
    <!DOCTYPE html>
    <html>
    <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
    </head>
    <body>
    <h1>Sample App</h1>
    <p>
      This is the home page for the
      <a href="http://www.railstutorial.org/">Ruby on Rails Tutorial</a>
      sample application.
    </p>
    </body>
    </html>
    
  19. app/views/layouts/application.html.erb

    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
    
  20. .erb的內容會轉換成HTML,然後放到<%= yield %>裡面
    visiting the page /static_pages/home converts the contents of home.html.erb to HTML and then inserts it in place of <%= yield %>.

  21. <%= stylesheet_link_tag ... %>
    <%= javascript_include_tag "application", ... %>
    <%= csrf_meta_tags %>
    

    This code arranges to include the application stylesheet and JavaScript, which are part of the asset pipeline (Section 5.2.1), together with the Rails method csrf_meta_tags, which prevents cross-site request forgery (CSRF), a type of malicious web attack.

  22. 要記得把<!DOCTYPE html>,,

    ,這些HTML的結構清掉,才能放到.erb裡面。
    Of course, the views in Listing 3.28, Listing 3.30, and Listing 3.31 are still filled with all the HTML structure included in the layout, so we have to remove it, leaving only the interior contents.
  23. 改成root 'static_pages#home',會讓原本的static_pages/home失效

 
over 2 years ago

備註:ROR TUTORIAL (3RD ED.) Chapter 1 + RailsFun.tw 新手教學_day2 的整理

  1. 這邊的步驟,一台電腦只要設一次:

    $ git config --global user.name "Your Name"
    $ git config --global user.email your.email@example.com
    $ git config --global push.default matching
    $ git config --global alias.co checkout
    
  2. 首先要新建一個repo

    $ git init
    
    $ git init --bare prodject.git
    

    ps 這邊跟JC大講解的不一樣:RailsFun.tw 新手教學_day2 HD
    4:50 JC大:應該用 'git init --bare prodject.git'

  3. 把所有的檔案都夾到repo裡面去

    $ git add -A
    

    實際上,都還留在staging area,然後要commit跟給附註(-m)才能夠上傳。

  4. 用git status來看有什麼處在pending的改變

    $ git status
    
  5. -m 是用來寫附註的:

    $ git commit -m "Initialize repository"
    
  6. 設定好Bitbucket的帳號
    Public Key

    Listing 1.11: Printing the public key using cat.
    $ cat ~/.ssh/id_rsa.pub
    
  7. 設定遠端Bitbucket的repo origin,然後把本地端的東西上傳到遠端的repo
    每個新專案都要新增一個專屬的repo (Create a new repository),然後才可以上傳檔案。
    第一次上傳要使用$ git push -u origin --all,之後只要用git push
    Listing 1.12: Adding Bitbucket and pushing up the repository.
    設定遠端Bitbucket的repo origin

    $ git remote add origin git@bitbucket.org:<username>/hello_app.git
    

    第一次上傳

    $ git push -u origin --all # pushes up the repo and its refs for the first time
    

    The commands in Listing 1.12 first tell Git that you want to add Bitbucket as the origin for your repository, and then push your repository up to the remote origin. (Don’t worry about what the -u flag does; if you’re curious, do a web search for “git set upstream”.) Of course, you should replace with your actual username. For example, the command I ran was

    $ git remote add origin git@bitbucket.org:mhartl/hello_app.git
    
  8. 記得做任何比較大的改變之前,都要新增一個branch。
    checkout -b可以新增一個new branch,同時switch去這個new branch

    $ git checkout -b modify-README
    Switched to a new branch 'modify-README'
    
  9. 如果只是一些小改變,可以直接用git commit -a -m,可是如果有新增檔案,就必須先用git add -A然後再用git commit -m

  10. merge要先由branch去合併master,然後再由master去合併branch

    JC講的:RailsFun.tw 新手教學_day2 HD
    28:50

  11. -D是可以不用merge 就可以暴力把branch刪掉

    git branch -D topic-branch
    
  12. 有新的變更,就再用一次git push上傳到Bitbucket

    $ git push
    
  13. 版本(Git)做好之後,可以開始部署(deploy到Heroku)去Production了。

  14. Heroku 使用 PostgreSQL database

    :production 要用pg (PostgreSQL)

    group :production do
    gem 'pg',             '0.17.1'
    gem 'rails_12factor', '0.0.2'
    end
    

    Note also the addition of the rails_12factor gem, which is used by Heroku to serve static assets such as images and stylesheets. Finally, be sure to incorporate the changes made in Listing 1.5 preventing the sqlite3 gem from being included in a production environment, since SQLite isn’t supported at Heroku:

    :development要用sqlite3

    group :development, :test do
    gem 'sqlite3',     '1.3.9'
    gem 'byebug',      '3.4.0'
    gem 'web-console', '2.0.0.beta3'
    gem 'spring',      '1.1.3'
    end
    

    雖然加上without production,不會在local端install pg跟rails_12factor這兩個gem,不過其實是更新到Gemfile.lock

    $ bundle install --without production
    
  15. 再把剛剛做的事情在commit一下

    $ git commit -a -m "Update Gemfile.lock for Heroku"
    
  16. Heroku setup

  17. 確定有沒有灌過heroku CLI跟Heroku Toolbelt

    $ heroku version
    
  18. 登入跟輸入SSH key
    Once you’ve verified that the Heroku command-line interface is installed, use the heroku command to log in and add your SSH key:

    $ heroku login
    $ heroku keys:add
    

    Finally, use the heroku create command to create a place on the Heroku servers for the sample app to live (Listing 1.15).

  19. 新建一個網址

    $ heroku create
    
  20. 在push到heroku master,就好了

    $ git push heroku master
    
  21. push之後,記得要migrate the production database (chapter 2 才提到這件事情 2.3.5 Deploying the toy app)

    $ heroku run rake db:migrate
    
  22. 如何在上傳Heroku之後,還可新增使用者跟管理者

    $ heroku run rails console
    

    Getting Started with Rails 3.x on Heroku

 
over 2 years ago

6:00 先從架構開始
HTML5

<body>
  <main>
    <aside></aside>
    <div></div>
    <aside></aside>
  <main>
</body>

7:40 先看左邊的<aside></aside>

<class='main'>

.main {
  width:100%;
  height:100%;
}

<class='sidebar'>

.sidebar {
  width:100px;
  height:100%; *從上到下
}

9:40

<html><body>要記得設大小,裡面的div們才會出現。

html , body {
    width: 100%;
  height: 100%; 
  padding: 0px; 通常都會設為0
  margin: 0px; 通常都會設為0
}

ps:不過,如果要把navbar固定在最頂端,就要把body的padding做修改。
[https://getbootstrap.com/components/#navbar-fixed-top]
譬如:body { padding-top: 70px; }

11:30 開始做logo
<aside>裡面做一個class='logo'<div>

.logo {
    background-image: url();
  #還是要記得設寬跟高
  width:64px;
  height:83px;
  margin: 0 auto 0 auto; 這樣可以置中
}

13:50 開始在logo下面用<ul>作清單,目標是讓清單(menu)置中

<aside>
  <ul class='menu'>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</aside>

因為menu會有預留的空間,所以要改padding=0,才有辦法去把文字置中

.menu {
    display: inline-block;
    padding: 0px;
    margin: 0 auto;
}
.menu li {
    #去除點點
    list-style: none;
}

還要回去改sidebar,才能讓menu置中

.sidebar {
  width:100px;
  height:100%; *從上到下
 **text-align: center;**
}

23:00 打出中間內容(content)的部分

<body>
  <main>
    <aside></aside>
    <div class='content' >
      <div class='top_menu' > </div>
      <div class='banner' > </div>
      <article> </article>
    </div>
    <aside></aside>
  <main>
</body>
.top_menu{
    height: 30px;
}

25:00 要在main的地方新增flex(CSS 3)

.main {
  width:100%;
  height:100%;
  **display:flex;**
}

content的地方也要加相關的東西

.content {
  flex:1 #占滿aside剩下的所有的空間,所以要去把右邊的aside也加上固定的寬度。
}

26:40 右邊的aside,取名為detail
<aside class='detail'></aside>

.detail{
width: 120px;
}

28:00 把top_menu做成半透明的黑色

.top_menu {
    height: 30px;
  background-color: rgba(0,0,0,0.5);
}
 <div class='top_menu' > 
   <div class='account' > 
   </div>
 </div>

28:00 放兔子的圖檔

 .account {
   background-image: url();
   width:22px;
   height:37px;
   display: inline-block;
   margin: -7px 0 0 10px;
 }

33:00 下拉選單

 <div class='top_menu' > 
   <div class='account' > 
   </div>
   <select>
     <option value=''>AAA</option>
     <option value=''>BBB</option>
   </select>
 </div>

像select這樣的元素,預設就是inline-block,具有寬跟高。有一個垂直對齊的功能 - vertical-align

 .account {
   background-image: url();
   width:22px;
   height:37px;
   display: inline-block;
   margin: -7px 0 0 10px;
   vertical-align: middle; #這樣就能垂直置中select了。
 }

33:00 用CSS調整下拉選單的樣式
先把本來的外觀拿掉

element-style {
    background-color:transparent;
  border: 0px;
  -webkit-appearence: none; (會把箭頭弄不見)
}

用開發者工具來看

select {
-webkit-appreance:multilist; (把這個改成none)
}

<select id ='dropdwon'>

#dropdown {
    background-color:transparent;
  border: 0px;
  -webkit-appearence: none; (會把箭頭弄不見)
  cursor: pointer; (增加滑鼠指標)
}

用after做出向下的箭頭 (後來發現select不能用這招after)

#dropdown:after {
    content:'↓';
  display:inline-block;
  height: 16px;
  width: 16px;
}

在select後面再加span就出現了,然後用after幫span做出向下的箭頭

46:00 在select後面做搜尋按鈕,然後置右

 <div class='top_menu' > 
   <div class='account' > 
   </div>
   <select>
     <option value=''>AAA</option>
     <option value=''>BBB</option>
   </select>
  <div class='search-wrapper'> <input type='text' class = 'search'><a href='#' 搜尋 a></div>
 </div>
.search {
    border-radius:5px;
    float:right;
}
.search-wrapper {
    float:right;
}

53:00 開始給banner一張圖片

<body>
  <main>
    <aside></aside>
    <div class='content' >
      <div class='top_menu' > </div>
      <div class='banner' > </div>
      <article> </article>
    </div>
    <aside></aside>
  <main>
</body>
.banner {
  background-image: url("");
  width:;
  height:279px;
  background-repeat: no-repeat;
  background-postion: center 0;
  background-color: white;
}

53:00 banner下面放點點

nav其實跟div沒甚麼差別,只是給一個名字而已,為了讓google機器人看的

<body>
  <main>
    <aside></aside>
    <div class='content' >
      <div class='top_menu' > </div>
      <div class='banner' > </div>
      <nav class = 'nav'>
        <span>●</span>
        <span>●</span>
        <span>●</span>
        <span>●</span>
        <span>●</span>
      
      </nav>
      <article> </article>
    </div>
    <aside></aside>
  <main>
</body>
nav span {
 font-size:150%;
}

1:00:00 開始講article

<article> 

<div class='title'> 熱門排行 <span class='bullet'></span></div>
</article>
div.title {
  background-color:;
  display:inline-block;
  width:5px;
  margin-left:2em; (2個字元的寬度)
}
div.title > span.bullet {
  background-image: img(""); #這裡怎麼突然變成img?
  display: inline-block;
  width:26px;
  height:21px;
  vertical-align:text-bottom;
}

1:07:00 放一堆圖片

 
over 2 years ago
$number_of_grades = 0 #integer
$grade_sum = 0.0 #float
$gpa = 0 #integer
def convert_letterGrade_to_number(letter_grade)
    grade = 0;
    case letter_grade
    when "A"
        grade = 4.0
    when "A-"
        grade = 3.7
    when "B+"
        grade = 3.3
    when "B"
        grade = 3.0
    when "B-"
        grade = 2.7
    when "C+"
        grade = 2.3
    when "C"
        grade = 2.0
    when "C-"
        grade = 2.0
    when "D"
        grade = 1.0
    when "F"
        grade = 0.0
    else 
        puts ""
    end
    grade
end
 def does_user_say_no(quesiton)
     quesiton == "stop"
 end
 def get_user_grade_and_add_all
     
     user_input = ""
     
     // we need to increnment the grade_counter
     grade_counter = 0
     
     // this part of code will continue to run until the user says no
     until does_user_say_no(user_input)
         // where to get the input from the user
         user_input = gets.chomp
         
         // user input should be convert to a number or a value
         $grade_sum += convert_letterGrade_to_number(user_input)
         
         grade_counter +=1
     end
     
     //we want to hold the value of the counter
     $number_of_grades = grade_counter -1 
     
     //at the end of the methed, when the calculation is done, we want to return sum of the grade 
     $grade_sum
 end

# the method actually calculate the GPA

 def calculate_gpa
     $gpa = get_user_grade_and_add_all / $number_of_grades
     $gpa #at the end, return the value of GPA.

 end

#For the last part call the method, store the variable say myGrade

 myGrade = calculate_gpa
 puts  myGrade

下面這邊忘記是在幹嘛的了

def map_it(array)
    i = 0
    out = []
    while i < array.size
        out << yield(array[i])
        i +=1
    end
    out
end
name = ["alice","bob","charlie"]
map_it(name) do |item|
    item.reverse
end
     
 
over 2 years ago

來源:RailsFun.tw 新手教學 day2.5 HD

00:01:45

rails new 之後
要先設定database.yml

default:
    adapter:mysql2
    username:
    password:

production:
    username:
    password:

00:02:00

gem 'will_paginate'
gem 'awesome_print'
gem 'rails-pry'
gem 'devise'
gem 'paperclip'

bundle install

00:04:35

先設routes,只要他的首頁

routes.rb
resources :statics, only =>[:index]

namespace是一個特殊的結構

routes.rb
namespace :dashboard do
    resources :items
end

會變這樣:

/dashboard/items/action

00:08:00

admin建議取成亂碼

從管理介面開始打,因為管理頁面會比前台多

routes.rb
namespace :dashboard do #使用者介面

    resources :orders
    namespace :admin do #管理者介面
      resources :items
      resources :cates
      resources :orders
      resources :users
      resources :managers
     end

end

00:09:00

gem devise

00:18:00

mysql2的最新版本有問題,'0.4.0'
所以要在Gemfile裡面指定版本

gem 'mysql2' , '0.3.20'

00:19:00

rails g devise User
rails g devise Manager

之後,migration的檔案裡面要做些什麼修改

00:23:00

弄一個新的migration設定items 跟cates

create_table :items do |t|

記得要加軟刪除

t.timestamp :delete_at

00:29:00

建議要加add_index

add_index :order_items, [:order_id]

建議用array []
所有會被where到的都要加index
所有會關聯到的column都要加index

create_table :order_items do |t|
    t.interger :order_id, :null => false 要加
    t.interger :item_id, :null => false 要加
    t.interger :user_id, :null => false 要加
    t.interger :price, :null => false
end

00:31:00

gem paperclick
一定要用imagemagic

00:33:35

要做相簿式的話,可能需要一對多的表

00:34:00

參考railsfun的文章,可以把
cover_file_name, cover_content_type, content_file_size, cover_update_at都刪掉

00:35:00

manager.rb,管理員不允許被註冊,所以:registerable要砍掉

00:37:00

item.rb
講paperclip的使用,railsfun有專文

styles: {
    original: 預設會有,所以要把他設好
}

00:41:00

items要加cates的column

add_column :items, :cate_id, :integer, :null => false

一個item一定要歸在某個分類

00:45:00

開始打controller,繼承結構很重要

有兩個namespace,就要建兩個資料夾
mkdir dashboard
mkdir admin

class ApplicationController < ActionController::Base

如果不想被ApplicationController所影響,可以直接繼承ActionController::Base。
如果要偷懶,可以繼承ApplicationController。所以方便性會增加。
=> 繼承ApplicationController就好

要另外做一個dashboard_controller.rb
使用者要登入,才可以進來
之後繼承Dashboard::DashboardController,都不用再打一次before_action

dashboards_controller.rb
class Dashboard::DashboardController < ApplicationController
    before_action :authenticate_user!
end

(Dashboard::DashboardController,意思是namespace::controller,namespace下面的controller)

譬如:orders_controller.rb,就不用再打一次before_action
不過前面還是要記得加Dashboard::

oders_controller.rb : 這邊的寫法,代表繼承Dashboard::DashboardController
class Dashboard::OrdersController < Dashboard::DashboardController

end

要另外做一個admin_controller.rb

admin_controller.rb
class Dashboard::Admin::AdminController < ApplicationController
    before_action :authenticate_manager!
end

(1) Dashboard::Admin:namespace下面的namespace
(2) Admin::AdminController:這層namespace的第一個controller (第一個通常會跟namespace的那個相同名稱)
(3) Admin::AdminController < ApplicationController:第一個controller,所以要繼承ApplicationController
(4) 第一個controller:打一次before_action,之後下面繼承的就不用打了

items_controller.rb:不用再打一次before_action :authenticate_manager!
class Dashboard::Admin::ItemsController < Dashboard::Admin::AdminController 

end

00:53:00

用console 建管理員,不能夠有管理員的註冊頁面

1:00:00

開始講will_paginate

@items = @paginate = Item.paginate(:page => params[:page])

多加一個@paginate
在前端會很好用,就可以寫在:

veiws/layouts/application.html.erb
<%= will_paginate @paginate if @paginate %>

1:05:00

開始講登入、登出、註冊的按鈕
有裝devise,就可以用current_user或current_manager
取決於Model name

<% if current_user %>
    Hi <%= current_user.email %> 
    <%= link_to "登出" , destroy_user_session_path, :method => "delete" %>
<% else %>
    <% link_to "註冊" , new_user_registration_path %>
    <% link_to "登入" , new_user_session_path %>
<% end %>

1:15:00

開始手動改scaffold的檔案

1:18:00

因為有namespace的關係,所有_form.html.erb會有錯,要把<%= form_for (@item) do |f| %>
拉到外面那一層去。裡面只剩下submit就好

path也要改掉,edit的下一步是update,所以要改成update的path

edit_items_html.erb
<%= form_for(@item, {:url => dashboard_admin_item_path,:method => 'patch'} do |f| %>
    <%= render 'form' %>
<% end %>
new_items_html.erb
<%= form_for(@item, {:url => dashboard_admin_items_path,:method => 'ppost'})do |f| %>
    名稱<%= f.text_filed :name %></br>
<% end %>

在1:45:00 會重新修改
用form_for helper rails去找form_for的document
會發現form_for後面要有url

1:26:00

開始講admin / dashboard / application 的layout的差別

使用者頁面:

layouts/dashboard.html.erb

不需要 if current_user,因為已經強制登入了

後台頁面:

layouts/admin.html.erb

不需要 if current_manager,因為已經強制登入了
要改成manager.email
可以把各種管理選單打在這邊
如:商品的index頁面

<ul>
    <li><%= link_to "商品管理", dashboard_admin_items_path %></li>
</ul>

記得要到controller裡面加上

admin_controller.rb
layout 'admin'
dashboard_controller.rb
layout 'dashboard'

所有繼承他的controller都會套用layout

1:30:00

因為之前建過items.rb與cates.rb了,所以scaffold之後的migrate會出現問題,到migrate裡面把重複的檔案刪掉就好

1:31:00

解釋為什麼不能用is_admin

1:35:00

開始講faker

100.times do |i|
    Item.create(:name => Faker::Address.state, :price => rand(1..3000), :cate => '大雜燴')
end; true
Faker::Internet.user_name

3.times do |i|
  user_name = Faker::Internet.user_name
  email = "#{user_name}@example.com"
  password = "#{user_name}" + "#{user_name}"
    User.create(:name => user_name, :email => email, :password => password) 
end;true

User(id: integer, name: string, created_at: datetime, updated_at: datetime, email: string, encrypted_password: string, reset_password_token: string, reset_password_sent_at: datetime, remember_created_at: datetime, sign_in_count: integer, current_sign_in_at: datetime, last_sign_in_at: datetime, current_sign_in_ip: string, last_sign_in_ip: string, avatar_file_name: string, avatar_content_type: string, avatar_file_size: integer, avatar_updated_at: datetime) 

https://cuppycode.wordpress.com/2013/04/08/creating-dummy-users-with-faker/

10.times do |n|
      puts "[DEBUG] creating user #{n+1} of 10"
      name = Faker::Name.name
      email = "user-#{n+1}@example.com"
      password = "password"
      User.create!( name: name,
                    email: email,
                    password: password,
                    password_confirmation: password)
    end

1:37:00

item一定要有一個default的cate_id
(41:00設定:null => false)

1:39:00

後台通常都是倒敘排序:DESC

def index
    @items = @paginate = Item.order('id DESC').paginate(:page => param[:page])
end

1:40:00

redirect_to :action => :index

會等於redirect_to xxx_path

1:42:00

開始講private

def item_params
    params.require(:item).permit!
end

1:47:00

edit送出後,出現錯誤訊息nilClass
表示update的地方出錯了
加上

@item = Item.find(params[:id])

就好了

1:47:35

開始要來加圖片了

edit.html.erb
<% f.file_field :cover %>

1:52:00

在產品列表頁的地方

<%= image_tag item.cover.url(:icon), :width => 150, :height => 150 %>

1:53:00

開始講SELECT
用rails helper select form搜尋
類別

<%= f.select :cate_id, Cate.all.map{ |c| [c.name, c.id]}%>

1:57:00

view的地方要顯示類別需要一個join的動作,不然log的地方會很醜
1:58:48 log很醜
每次找item,都會到表去抓一次cate
一定要解決,不然會拖累效能
出現這樣的log代表view是有問題
解法在controller內

def index
    @items = @paginate = Item.includes(:cate).paginate(:page => params[:page])
end

加上includes就好了
先去把所有的item拉出來,去找裡面的cate id 到底有多少個,只有四個,然後再全部拉出來,再拼回去

1:59:20

醜的

SELECT `items`.* FROM `items` LIMIT 30 OFFSET 0
SELECT `cates`.* FROM `cates` WHERE `cates`.`id` = 7 LIMIT 1

2:00:00

漂亮的

SELECT `items`.* FROM `item` LIMIT 30 OFFSET 0
SELECT `cates`.* FROM `cates` WHERE `cates`.`id` IN (7,4,9,1) 

2:01

item_controller
item/index.html.erb

2:03

<td>加入購物車</td>
<%= image_tag item.cover.url(:icon) %>

2:04:45

加入購物車這件事情很困難
要配javascript跟session,不然做不起來

先去items_controller

(1) 預計會給id,所以要先去加route

def add_cart

end

(2)

resource :items do
    memeber do (單一產品,會有id)(items/:id/yoo)
    end
    collection do (當作集合體)
    end
end

(3) 先寫route

resource :items do
    memeber do (單一產品,會有id)
      get :add_cart  
    end
    collection do (當作集合體)
    end
end

2:08:20

(1) 回到items_controller

items_controller
def add_cart
  params[:id] #會得到item的:id 觀察routes

  session[:cart] ||= {}  :cart是自訂
  #hash跟array都可以,不過array會有次序性,可以追蹤足跡,購物車用{}就好

end

2:09:45

(1)

def add_cart
  
  session[:cart] ||= {}  :cart是自訂
  #這是initialize,如果沒有的話,塞進{},如果有的話,不動session[:cart]

  
  會得到params[:id],但要先驗證params[:id]存不存在
  item = Item.where(:id => param[:id].first
  #不用@變數,因為沒有view,所以用區域變數item


  if item (如果有item的話)
  session[:cart][item.id] ||= 0
  session[:cart][item.id]  +=1
  end
  render :json => {:counter => session[:cart].length}.to_json #最後得到一個:json,也就是一個counter(key)對一個數量(value)


end

2:12:20

layout/application.html.erb

2:12:40

app/helpers/application_helper
view可以直接用 => layout/application.html.erb
def get_cart_count #如果session有東西,把長度丟出去,沒有就丟0回去

    if session[:cart]
        return session[:cart].length
    else
        return 0
    end
end
layout/application.html.erb
<div>購物車數量: <span id="cart_counter"><%= get_cart_count %></span></div>

記得加span,因為等一下要用ajax的東西
get_cart_count這是剛剛的helper

2:16:00 開始要弄ajax

view/layout/application.html.erb

2:16:30

(1) 在view/layout/application.html.erb挖洞
要放javascript跟css的地方

view/layout/application.html.erb
<head>
        <%= yield :header %> =>  對應 
        <% content_for :header do %>
</head>

(2) 加到item/index.html.erb

item/index.html.erb
<% content_for :header do %>
<% end %>

(3) 這是jQuery的ready語法

<script>
    jQuery(function($)){

    };

</script>

2:18:00 加入購物車這個超連結要做的事情

<td><a href="#" class="add_cart", data-value="<% item.id %>">加入購物車</a></td>

class="add_cart"是為了jQuery
data-value="<% item.id %>

value是item的id
data-value也是jQuery的用法

2:18:00

<script>
    jQuery(function($)){
     $('.add_cart').click(function(){ 
        #當我按下去$('.add_cart')(加入購物車)之後要幹嘛,我預設按下去之後會增加到購物車的URL,而且用GET的方式去做,他就會touch他之後再回給我東西

     })
    };

</script>

2:19:45

rake routes找購物車的網址,前面是get

add_cart_item => /item/:id/add_cart

(add_cart Method)
(為了要找到item的id)

2:19:55

(1) jQuery有一個語法是$.

<script>
    jQuery(function($)){
     $('.add_cart').click(function(){ #當我click之後要幹嘛,我預設按下去之後會增加到購物車的URL,而且用GET的方式去做,他就會touch他之後再回給我東西

        $.getJSON('/item/:id/add_cart') #click之後,會跑到add_cart這個method去執行,最後render這個網址的Json

     })
    };

</script>

(2)2:20

'/item/:id/add_cart'

:id是我們需要填值的地方

<script>
    jQuery(function($)){
     $('.add_cart').click(function(){ #當我按下去之後要幹嘛,我預設按下去之後會增加到購物車的URL,而且用GET的方式去做,他就會touch他之後再回給我東西

        $.getJSON('/item/'+ $(this).attr('data-value') + '/add_cart') 
        #要把:id改成正確的網址,所以要去找到 data-value

        #預設會是id進去,所以我們要把id取回來:data-value="<% item.id %>"value是item的id


     })
    };

</script>

(3) 得到網址後,預計會得到一個jSON回來: function(json){},json回來後,要去更新購物車數量$('#cart_counter')

<script>
    jQuery(function($)){
     $('.add_cart').click(function(){ #當我按下去之後要幹嘛,我預設按下去之後會增加到購物車的URL,而且用GET的方式去做,他就會touch他之後再回給我東西

        $.getJSON('/item/'+ $(this).attr('data-value') + '/add_cart') , function(json){
            $('#cart_counter').html(json.counter);

        }
        #得到URL之後,預計會得到一個jSON回來: function(json){}

        #json是要去更新到某一個地方 => $('#cart_counter'),也就是購物車數量:0 

        (<div>購物車數量: <span id="cart_counter"><%= get_cart_count %></span></div>)

     })
    };

</script>

2:21:00

看item_controller的最後一步,會有 render :json => {:counter => session[:cart].length}.to_json
不管if的地方的結果是什麼,最後都會得到一個counter(key)對一個數量(value)

這邊function(json),最後會得到json.counter

:json => :counter

function(json){
$('#cart_counter').html(json.counter);
}

2:21:50

要在click最後面加false,因為如果不想觸發那個按下去的event的話,

2:22:30

噴了之後,要看500

去console看500
點500的連結,會跑到Network去
然後再refresh一次,會將錯誤的地方標成紅色的。
add_cart出現錯誤
看Response

其實console log也可以看到error
(這邊其實只是字打錯)

2:25:00 講debug

layout/applicationn.html.erb
<%= session[:cart] %>

就可以看出來每一個品項點了幾次

2:26:00 看為什麼品項沒有變化

items_controller

2:27:00

發現要改成string

2:27:50 發現要把item.id從string改成integer

(JC說要session[:cart][key]變string,可是打.to_i)

2:28:00

可是後來又打成.to_s

if item
    key = item.id.to_s
    session[:cart][key] ||=0
    session[:cart][key] += 1

2:28

{"1" => 6.....}沒有jax所以不會馬上動

2:29:00

開始教CSS

真正上production都會用ul跟li

2:36:30

之後就是去做結帳的動作
把session去做結帳動作
把session的item列出來
"1" => 6
item的id 數量是value
送出:建立一張order,上面就是所有的item
使用者在後台可以看到,列出所有項目,然後付款

2:38:00

建一個Status

order.rb
has_many :order_itemm

STATUS = [['新增',1], ['付款中',2], ['已對帳',3],['已出貨',4]]['問題單', 5]]

接到SELECT TAG

關掉再進入還在
登出再登入 / 換瀏覽器 就會清除session

2:42:25

可以不用session做,可以開table來塞
誰,物品,跟數量

 
over 2 years ago

Ruby-02

new = initialize 兩個是一樣的

class Car

def initialize(name, color)
@name = name
@color = color
end

5:00
getter/setter是一組的
attr_accessor =>就是getter和setter
attr_writer =>就是setter
attr_reader =>就是getter

09:40
多層的module/class/常數

16:00
限制:Instance method
public/private/protected

protected是給繼承用的
在Class Cat裡面設定protected的method
然後 Class Dog < Cat
之後,Dog才能用proteced的那個method,Cat本身不能用

24:00
限制:Class method
a. public_class_method :class_method_name
b. private_class_method :class_method_name

Class的self.method如果只寫private會沒用 (instance的才有用)

要強制寫成
private_class_method :hooo
這樣才不會被叫到

26:30
operator methods 數學運算式

31:00
alias_method:new_name, :old_name

37:00
method_missing

47:00
ENV
ARGV 跟 gets

56:00
FILE

1:02:50
演算法的Hash
md5
sha1
hmac
rainbow table 與 salt

require 'digest'
Digest::MD5.hexdigest("hello world")
Digest::SHA1.hexdigest("hello world")
Digest::SHA256.hexdigest("hello world")
Digest::SHA512.hexdigest("hello world")

devise用的是HMAC,不過不算是hash
是一堆演算法聚集起來的一種方式
把很多雜湊兜一兜

1:11:00
File
yaml
csv
nokogiri

1:37:00
Regexp
rubular
regexcrossword

1:46:00
怎麼使用Regexp
match = "A123456789".match(/[A-Za-z])(0|1)(\d{8})/)

1:48:00
encode
encoding

1:51:00
ri
rdoc

1:54:00
sinatra:ruby 裡面最簡單的html server
eventmachine - em-websocket

2:00:00
Deploy

  1. gem install passenger
  2. passenger然後按tab兩次,可以看到什麼可以用
  3. 有兩個的gem可以用 passenger-install-nginx-module / passenger-install-apache2-module
  4. rvmsudo passenger-install-nginx-module
  5. touch tmp/restart.txt

2:04:00
Cache的手法
rails cache
http://guides.rubyonrails.org/v3.2.17/caching_with_rails.html

Page Caching:把整頁的html都存成一個檔案,會遇到很嚴重的dirty data的問題(A看到B看過的網頁)

Fragment Caching:某一部份的網頁會被cache住
缺點:

2:09:00
Memcached
dalli
在production的環境下建議一定要用dalli,可以減少cookie的使用量

gem dali
https://github.com/petergoldstein/dalli

會把session丟過來Memcached
可以減少header的量

2:12:00
Redis:
http://redis.io/
key by value的結構,是在記憶體內,所以速度會很快
很重要
多重server之間的溝通跟一些cache的動作

2:18:00
用兩個視窗來表演同步的redis
Redis Pub/Sub... How Does it Work?
https://robots.thoughtbot.com/redis-pub-sub-how-does-it-work
pub/sub
$redis.subscribe('rubyonrails', 'ruby-lang') do |on|
on.message do |channel, msg|
data = JSON.parse(msg)
puts "##{channel} - [#{data['user']}]: #{data['msg']}"
end
end
訂了兩個channel

$redis.subscribe('hoo', 'yoo') do |on|
on.message do |channel, msg|
data = JSON.parse(msg)
puts "c: #{channel}, say: #{msg}"
end
end

左邊打 $redis.publish('hoo', 'hihi')
右邊會把上出現 c: hoo, say: hihi

server跟server間的推播

樹狀結構
master server接很多slave

一個clietn發出一個聊天訊息到slave server,
slave 把訊息丟給master
server,master做了處理之後,發給所有的slave,
所有slave在廣播給所有的使用者

為什麼要過slave:因為一台server撐不了太多的connection,所以會建議多開幾台slave

 
over 2 years ago

00:01:00
偽Thread
setTimeout
setInternal/clearInternal
setInterval/setTimeout

00:16:00
window

00:24:00
JQuery

slector基本上跟CSS一樣。

(1) yoo
(2) moo
(3) woo
(4) coo

jQuery(function($){}); //這是ready的意思

jQuery(function($){
$('span') //上面四個span都會被選到
});

jQuery(function($){
$('span#moo') //只會選到(2)
});

jQuery(function($){
$('#moo') //只會選到(2),跟上面那個是一樣的
});

jQuery(function($){
$('span.woo') //只會選到(3)
});

特殊寫法
jQuery(function($){
$('[data-id='coo']') //只會選到(4)
});

00:27:00
$ === jQuery
所以$('[data-id='coo']') 跟jQuery('[data-id='coo']')
的意思是一樣的

set的操作
find/first/siblings/parent/parents/end

00:40:00
binding event:click/mouseover/mouseout/keyin/keyout/keypress/focus

jQuery(function($) {
$('span').mouseover(function(){
$(this).addClass('active');
}).mouseout(function(){
$(this).removeClass('active')
})

00:42:00
event.stopPropagation()

CSS設好之後,會變成一個一個的方框,按其中一個方框,卻會啟動所有方框都執行jQuery,所以要加event.stopPropagation()
jQuery(function($){
$('div').click(function(event){
$(this).addClass('active');
event.stopPropagation();
})

00:49:00
bind vs on(live)優缺點

(A)
jQuery(function($) {
$('span').mouseover(function(){
$(this).addClass('active');
}).mouseout(function(){
$(this).removeClass('active')
})

(A) (B)的效果是一樣的

(B)
jQuery(function($) {
$('span').bind('mouseover', function(){
$(this).addClass('active');
}).bind('mouseout', function(){
$(this).removeClass('active')
})

bind的功能

  1. 當javascript有新一個jQuery還沒有的新功能的時候,可以用bind加進來。 2.可以上namespace

00:54:00
實作一個動態增加欄位的form

  • 請輸入密碼 add del

1:00:00
railsfun params的包裝與使用

/?name=hihi&title=meow

=> params = {:name => 'hihi', title => 'meow'}

/?name=hihi&name=yoo

=> {:name => 'yooo}

hihi會遭到覆蓋

/?name[]=hihi&name[]=yoo

=> {:name => ['hihi','yoo']}

array建立法

/?name[]=yoo&title[]=hoo

=> {:name => ['yoo'], :title => ['hoo']}

array多層

/?name[title]=yoo&name[age]=18

=> {name => {:title => yoo', :age => '18'}}

Hash建立法

/?name[title][]=yoo&name[title][]=hoo

=> {:name => {:title => ['yoo', 'hoo']}}

Hash / Array混用

/?name[][] = yoo

=> {:name => nil}

用法錯誤,語意錯誤

1:03:00
Ajax簡單的實作

1:11:00
jQuery ajax
看jQuery的document
jQuery.ajax

1:24:00
無限分類下拉選單

1:27:00
JsonP

1:31:00
為何要用jQuery,為何要拋棄jQuery

1:39:00
推薦的書:
javascript Good part
Javescript Design pattern (不建議看)

1:41:00
其它lib的應用
jQeury UI

 
over 2 years ago

00:01:50

接續Day 4

.button.button2{ background-position: -130px 0;}
.button.button3{ background-position: -260px 0;}
.button.button4{ background-position: 0 -130px;}
.button.button5{ background-position: -130px -130px;}
.button.button6{ background-position: -260px -130px;}

滑鼠變化

.button.button2:hover{ background-position: -260px 0;}

vertical align

<div class ='head'>
    <span>img</span> im_title
</div>
.head{
    line-height: 60px;
    vertical-align: middle;
}

span{
    display: inline-block;
    width: 60px;
    height: 60px;
    text-align: center;
}

00:02:20

float/clean/.clearfix(:after)

float:left
文繞圖,文比圖多
圖先找到位置,文再跑去旁邊
會有一個問題(不知道怎麼打)
但是可以用clearfix:after解決
參考:.clearfix:after

.clearfix:after{
    visibility: hidden; //我會佔位置,但是隱藏掉
    display: block; //block是區塊,會從頭延伸到尾,
    font-size: 0px;
    content: ''; //用空格來代替
    clear: both;
    height: 0px;
}

<ul class='clearfix'>就可以解決這一個問題

:after是額外定義的

00:12:00

:before都用在font awesome了

00:14:00

<i class='fa fa-download fa-lg'>
::before
</i>

點::before會看到

.fa-download::before{
    cotent:'\f019';
}

字碼是f019,可以隨便改

00:21:00

開始講position
absolute 會往上去找relatvie,最上一層就是整個body
relative

position: absolute;
之後,會多出來top跟left這兩個屬性。

div{
    padding: 10px;
    margin: 10px;
}

div#layout{
    position: relative; //預設都是static
    width: 300px;
    
    //做會移動的banner時,把凸出去的藏起來
    overflow: hidden;
    //
    z-index: 999; // 數字越大越上面,不過還是沒辦法突破relative那層
}

div#content{
    postition: absolute; //如果.layout沒有設relative,那會繼續往上一層找有relative的,最後就會找到body去。
    top: 100px; //absoulte會多上下左右位置可以寫
    left: 10px;
  
  //會移動的banner,可以這樣設
  width: 100px;
  top: 10px;
  bottom: 10px;
  left: -1200px; //改變這個數字來移動圖檔,要用javascript來拖拉
  //不能用margin-left
  
}
<div id='layout'>
    <div id='content'>
    </div>
</div>

00:33:40

fix

<span class='cart'>buy me</span>
.cart{
    position: fixed;
    right: 10px;
    top: 10px;
}

00:35:40

做一個全螢幕不會跑掉的東西 - Popup Window (iQuery UI Dialog)

<div class= 'layer'></div>
.layer {
    position:fixed;
    top:0px;
  right:0px;
  bottom:0px;
  left:0px;
    background: rgba(0,0,0,0.4);
  z-index:99;
}

00:39:00

CSS打牌規則

inline > id > class > tag

鬼牌!important

ps. div.content可以贏過.content
ps. 寫在後面的.content可以蓋掉寫在前面的.content

.content {
    color:white;
}

.content {
    color:black;
}
//會出現黑色,不過如果變成color:white !important;,就會變成白色

00:48:00

RWD實作

<head>
    <meta name="viewport" content='width=device-width, initial-scale=1'/> 
  //要加這一行,不然手機裡面看到的還是電腦裡面的寬度
<style>
//先把整個架構做好,再去做細節
div, ul, li{
    background:rgba(0,0,255,0.3);
    list-style:none;
    padding:10px;
    margin:10px;
    border-radius:10px;
}
.wapper{
    width:1024px;
    margin: 0 autoo;
    position:relative;
}

.head{
    height:100px;
}

.menu{
    position:absolute; /固定在左邊
    top:140px;
    left:10px;
    width:100px;
    height:300px;
}

.content{
    margin-left:140px;
}

li{
    width:120px;
    height:120px;
    float:left;
}

//把他加在ul<ul class='clearfix'>,這樣才會撐開,不然ul li會怪怪的
.clearfix:after{
    visibility:hidden; //我會佔位置,但是隱藏掉
    display:block; //block是區塊,會從頭延伸到尾,
    font-size:0;
    content:' '; //用空格來代替
    clear:both;
    height:0;
}

RWD的code建議放在原生的code()的最下面

@media all and (min-width: N px) and (max-width: M px) {...}
通常都用max寬。
(A) max-width: 1024 px

@media all and (max-width: 1024 px){
    .wapper{
        width:auto; //因為wapper本來是定寬,改成auto之後,裡面包的東西就會跟著移動
    }
} 

(B) max-width: 768 px

@media all and (max-width: 768 px){
    .menu{ //會由直變橫
        position:static; //就不會往下移
        width:auto;
        height:auto;
    }
    .content{
        margin: 10px;
    }
} 

(C) max-width: 480 px

@media all and (max-width: 480 px){
    .li{
        
        width:100%; //還要再調整
        
    }
    
} 
</style>
</head>
<body>
    <div class='wapper'>
        <div class ='head'>
        </div>
        <div class='menu'></div>
        <div class='content'>
            <ul class='clearfix'>
                <li></li><li></li><li></li><li></li>
            </ul>
        </div>
    </div>
</body>

00:58:00

加上
1.<meta name="viewport" content='width=device-width, initial-scale=1'/>
viewport的寬度是devise的寬,要貼到head裡面

  1. @media all and (min-width: N px) and (max-width: M px){...} 要放在的最下面,先調最大尺寸(A),然侯往小尺寸一路往下設(B),然後用刪去法刪掉不要的

01:04:00

跨瀏覽器策略

01:08:00

bootstrap
Grid system

每個row裡面都分12等份

01:13:45

screen / print的分別

01:15:00

javasript
應該寫在body的最下面

01:19:00

console.log('')

01:21:00

區域變數 var temptemp = '123'
全域變數 temptemp='123'

執行一定要加括號

function hello(){
    var temp1 = 123;
    temp2 = 234
}

所有地方都可以執行temp2,因為他是全域變數,這樣不安全
只有在function hello裡面才可以執行temp1,在這裡面誕生,在這裡面執行完,這樣比較安全

不要隨便設全域變數
可以這樣設:

var temp2;
function hello(){
    var temp1 = 123;
    temp2 = 234;
}
hello();

先在外面把temp2設好,
之後在hello裡面給值去執行

1:25:00

javascript基本型別

ruby : 只有 nil , false為非
Javascript : 0 ,null, undefined , NaN 為非

console.log( 0|| null || undefined || NaN || 1);

只有跑出來1,表示前面的幾個都是非

javascript要寫三個等於 ===

1:32:00

迴圈的使用 for in
javascipt 的array

var temp = [1,3,5,2,9]
far(var i= 0 ; i < temp.length ; i++){
    console.log(temp[i]);
}

會print 出來 1,3,5,2,9

1:33:00

{}在javascipt是object

var temp = {wer : 123, sdf : "hello" , vcx : "kitty"}

for (var key in temp){
    console.log(key , temp[key]);
}

1:38:00

function的建立與使用

RUBY

def temp &block
    block.call(123)
end

temp do |i|
    puts i
end

會跑出來123

結果會跟javascript跑出來的答案一樣

function temp(func){func(123);}
temp(function(1){console.log(i)});也會跑出來123

1:51:00

區域變數的過水

console.log(temp.wer, tem.sdf , temp.vcx)

 
over 2 years ago

DEPLOY

passenger nginx

HTTP server:
Apache 跟 nginx 對static的網頁的支援比較好,也比較快,比較不佔資源。
不適合用在動態檔案,會傳到rails去處理
如果rails 沒有辦法處理,就跑404

DEPLOY完之後,用UNICORN,RAINBOW,PUMA,PASSENGER 會有watchdog去做process。如果人多,會開多一點process。人少會kill掉。

PASSENGER對新手比較簡單

00:04:00
gem install passenger
passenger 然後tab按兩下,會出現:

  1. passenger
  2. passenger-config
  3. passenger-install-apache2-module :可以裝在兩種http server上 - 老牌
  4. passenger-install-nginx-module :可以裝在兩種http server上 - 算新的,速度比apache快,不過每加一個外掛,就要重新compile一次。砍掉重來一次,或是蓋掉。
  5. passenger-memory-stats
  6. passenger-status

00:05:15
demo nginx

  1. 輸入passenger-install-nginx-module
  2. 一直按下一步
  3. 1 YES: download, compile and install Nginx for me.
  4. 選擇安裝的地方 /home/imroot/nginx 會出現permission denied,要用rvmsudo sudo跟rvm sudo (提權指令) 使用者沒有權限去動root的sudo

00:08:00
sudo ruby
會出現:[sudo] password for imroot:
sudo: ruby: command not found
rvmsudo ruby才可以動

所以要重打1: rvmsudopassenger-install-nginx-module

  1. 推薦的 /opt/nginx linux 的人喜歡用的: /usr/local/nginx 是sudo權限,所以可以灌到任何地方 JC用這個: /home/imroot/nginx

00:14:00
結束之後,有幾個地方最重要
A:

http{
    ...
    passenger_root /home/imroot/.rvm/gems/ruby-2.1-head/gems/passenger-4.0.50; (passenger的路徑)

    passenger_ruby /home/imroot/.rvm/gems/ruby-2.1-head/wrappers/ruby; (passenger要用的ruby的路徑)
    ...
}

00:16:00:要複製,不複製會出事
B:

server{
    listen 80;
    server_name www.yourhost.com;
    root /somewhere/public; #<--be sure to point to 'publi'!
    passenger_enable on;

}

00:17:00
根目錄下
nginx/conf/nginx.conf
(nginx的設定檔)
sudo vim nginx.conf
(因為是唯讀,所以要用sudo開)

這個應該已經設定好了:
A:

http{
    ...
    passenger_root /home/imroot/.rvm/gems/ruby-2.1-head/gems/passenger-4.0.50; (passenger的路徑)

    passenger_ruby /home/imroot/.rvm/gems/ruby-2.1-head/wrappers/ruby; (passenger要用的ruby的路徑)
    ...
}

server的地方是要動的地方:
C:

server {
    listen 80;
    server_name localhost;
    #charest koi8-r;
    #access_log logs/host.access.log main;
    location / {
    root html;
    index index.html index.htm;
    }
    #error_page 404 /404.html;
    #redirect server error pages to the static page /50x.html
    #
    error_page 500 502 503 054 /50x.html;
}

把B的這兩行貼在C裡面
然後改成

root /somewhere/public; #<--be sure to point to 'publi'!
passenger_enable on;

=>

root /home/imroot/shop/public ; #<--be sure to point to 'publi'!
passenger_enable on;

這個也可以刪掉

location / {
    root html;
    index index.html index.htm;
    }

00:19:00
要執行的時候
/nginx/sbin
sudo ./nginx 就是開啟
sudo ./nginx -s stop 是關掉

真正的主機位置是IP
如果錯誤的話,要看兩邊的log,一個nginx的,一個rails

先看rails 的錯誤
shop/log
tails -f production.log
然後重新整理網頁

在看nginx
/nginx/logs/vim error.log
Devise.secret_key was not set. please add the following to your Devise initializer:

所以要回去shop/config/initializers/devise.rb
config.secret_key的註解消掉

然後把nginx 重開一次

結果rails 的key又沒有
/shop/congif/secrets.yml

可以研究ruby secureramdom
require 'securerandom'
SecureRandom.hex(64)

00:25:00
產生之後,放回去/shop/congif/secrets.yml的最後一行:

production:
secret_key_base:放這裡

結果還是有問題,
回到rails去看
shop/log tail -f production.log
mysql2::Error (Access denied for user 'imroot'@'localhost' to database ('shop_production'))
要回去
``/shop/config/database.yml
這招偷來的,不要學:把development跟production的database打成同一個,客樣外部資料也可以啟動

development:
<<: *default
database :shop_development

production:
<<: *default
database :shop_production
username: imroot 改成root,上產品線的時候不能這樣
password: imroot

注意,絕對不要跟test打的一樣

00:28:00
重開rails而不重開nginx:用戶連線不會被中斷
passenger提供的方式:touch tmp/restart.text
192.168.11.46就可以用了

00:30:00
deploy最後的成果
ps-aux

00:32:00
在production模式下,如果去改檔案的話
再去重新整理網頁,是不會變動的
(在development模式下,refresh是會變動的)

所以在production模式下的時候,
要用touch tmp/restart.txt
網頁才會有變動

00:35:00
套用別人的模組
把別人的template 不要的code刪掉之後,
記得放<%= yiled %>
就會出現了

01:05:00
Hover之後,選項跟頁面同時在
class = "active"
這個地方很複雜

01:10:00
要把application.html.erb

<%= javascript_include_tag 'application'%>
<%= crsf_meta_tags %>

放到我們要的template裡面去
rails 的helper那些東西才能用

01:16:00
什麼是html

01:21:00
通常建議 <script src='/assets/jquery.js?body=1'></script>放在<body></body>的最下面
<style>CSS</style>則放在<head></head>裡面
因為,頁面要先出來後,再去觸發 javascript的event

01:25:00

jQuery(function($){ //ready的語法,先把這段code hold在記憶體內,等到body讀完之後,再去display,所以應該直接放在最下面就好了
    console.log('find_1*', $('#test')[0]);
})

就可以改成:console.log('find_1*', $('#test')[0]);
不需要ready(jQuery(function($){}))
javascript放在最上面還會佔用記憶體

01:28:00
開始講CDN:如果有一百張圖片,該怎麼抓 => BWOSER裡面的WORKER
一個domain name會有6-8個worker
domain name不一樣,就會有更多的worker,所以要切CDN

01:35:00
<img scr="wtf.png" title='cat' alt='cat'>
搜尋引擎跟機器人可以讀懂 title跟alt
把自己要用的東西這樣設定data-user-id='01'

01:47:00
不protocol連結
//192.168.11.46:3000
前面有兩的//
因為http跟https
一個沒加密,一個有加密

1:50:00
開始講CSS

可以寫成兩種格式
<link rel='stylesheet' href='hihi.css' media= "screen | print | both ">

或者是

<style>
body{
    
}

#id{
    
}
.class{
    
}

img.hihi.yoyo.logo#smile{
    要同時符合
}

</style>

1:56:00
<span>是文字區塊,可以跟別的東西並排
效果跟display:inline是一樣的

display:inline-block會變成圖片,
但是也可以跟文字同一行,文繞圖
變成圖片,所以可以設寬跟高

display:block,就是div(區塊)
會延展到底

所以都可以用span去做改變 inline, inline-block, block

2:04:00
開始講行高

<div class='head'>
    <span>im_title</sapn>
</div>
span{
    display:inline-block;
    background-color:#ccf;
    width:60px;
    height:60px;
    text-align:center;
}
.head , .head *{
    inline-height:60px;行高都設一樣,
    vertical-align:middle;然後置中對齊
}

02:08:00
講button:可以用一張圖做出多個button,可以減少worker數量

第一個button最好做

.button{
    display:inlone-block;
    background: url{/icons-390.jpg} no-repeat;
    width:130px;
    height: 130px;
    border:1px #ccc solid;
    margin: 10px;
    border-radius: 20px;
}
<span class='button button1'></span> 前面的當作主要的表述式,後面有數字的當作他的位移的動作
<a href="#"><span class='button button2'></span></a>
<span class='button button3'></span>
<span class='button button4'></span>
<span class='button button5'></span>
<span class='button button6'></span>

差異化

.button.button2{ background-position: -130px 0;}
.button.button3{ background-position: -260px 0;}
.button.button4{ background-position: 0 -130px;}
.button.button5{ background-position: -130px -130px;}
.button.button6{ background-position: -260px -130px;}

2:17:00
flukeout.github.io
CSS練習器