over 1 year ago

產生亂數的gif url

giphy.com提供的api來產生亂數的gif圖檔

app/models/random_gif_url.rb
class RandomGifUrl
  ENDPOINT='http://api.giphy.com/v1/stickers/random?api_key=dc6zaTOxFJmzC'
  def self.find
    new.find
  end
  def find
    parsed_response['data']['image_url']
  end
  private
  def parsed_response
    @parsed_response ||= JSON.parse(response)
  end
  def response
    Net::HTTP.get(uri)
  end
  def uri
    URI(ENDPOINT)
  end
end

RandomGifUrl.find即可產生亂數的gif url囉

 
over 1 year ago

自訂get帶參數

require 'open-uri'
uri=URI('http://blog.bro.tw')
    => #<URI::HTTP http://blog.bro.tw>

uri.query=URI.encode_www_form({a:123,b:"測試"})
    => "a=123&b=%E6%B8%AC%E8%A9%A6"
uri
    => #<URI::HTTP http://blog.bro.tw?a=123&b=%E6%B8%AC%E8%A9%A6>


 
over 1 year ago

Toastr

使用範例

gemfile
gem 'toastr-rails'

GEM連結

用flash方式套到前端

可將這部分放置layout內,記得要放在include_javascript之後

app/views/common/_flash_toastr.html.erb
<% flash.map do |type, message| %>
  <% toastr_types = { notice: :info,alert: :warning }%>
  <% toastr_type = toastr_types[type.to_sym] || type.to_sym %>
  <script>
    msg_show('<%= toastr_type %>','<%= message %>','BroHand訊息');
  </script>
<% end %>

在js中設定想要的參數

application.js
function msg_show(type, msg, title) {
  toastr.options = {
  closeButton: true,
  progressBar: true,
  showMethod: 'slideDown',
  timeOut: 4000
  };
  toastr[type](msg, title); //type:info,error,success,warning

}

使用它

controller中
  def index
    flash[:success]="test"
    flash[:alert]="test"
    flash[:info]="test"
    flash[:error]="test"
  end
 
over 1 year ago

案發原因

capybara-webkit gem 安裝時發生錯誤
通常是因為這個gem找不到qmake或者它發生錯誤

解法:安裝'qmake'

which qmake 看看本身有沒有安裝過,如果有的話刪掉它
brew install qt5 安裝它
brew link --force qt5 路徑給它
打完收工,之後bundle應該就不會有錯誤了!
參考連結

 
over 1 year ago

http://musicforprogramming.net/

 
over 1 year ago

Rails API

範例:http://grape-on-rails.herokuapp.com/
它的程式碼:https://github.com/ruby-grape/grape-on-rails

Gemfile
gem 'grape'

使用上遇到問題


server端需設定,才可以允許外部連結:

api
  before do
    header "Access-Control-Allow-Origin", "*"
  end
 
almost 2 years ago

案發現場


上傳我的專案到heroku後,跑出錯誤:undefined method 'find_asset'。

解決方法

會發生錯誤是因為,預設產品模式的設定。
所以修改產品模式的設定即可。

config/environments/production.rb
  #config.assets.compile = false

  config.assets.compile = true

參考連結

 
almost 2 years ago

案發現場

使用Binging.pry放在迴圈當中去debug,要想離開迴圈時需要一直輸入exit會有點崩潰!

解決方法

1.直接中斷

可以使用exit-programexit-p或者!!!直接中斷整個debug過程,但程式會整個終止!

2.關閉pry

若要順利的把整個程式執行完畢,要使用disable-pry,但事後要在controller中去把pry復原或者重開server。
ENV['DISABLE_PRY'] = nil

參考連結

 
almost 2 years ago

not to include Test::Unit
rails new <app_name> -T

clears all cache and sockets files
rake tmp:clear

rake assets:precompile

Using the figaro command, you can set values from your configuration file all at once
figaro heroku:set -e production

when use gem 'pg'
bundle install --without production

rails generate simple_form:install --bootstrap

rails generate controller home index --no-helper --no-assets --no-controller-specs --no-view-specs

rails g devise:install
rails g devise user
rake db:migrate
rails g devise:views
 
almost 2 years ago

案發現場

link_to("Delete", admin_product_path(product),method: :delete, data: {confirm: "Are you sure?"})
連結點下去只進入#show,不會進去#destroy。

追究原因

//= require jquery
//= require jquery_ujs << 這行不小心刪掉

Unobtrusive JavaScript

 
almost 2 years ago

啥情況

為了讓網站的前端加速,我們把大量javascript放到最後壓縮並載入,但若我們要讓一些自訂的javascript在載javascript區塊之後才執行,我們會使用自訂區塊來達到目的。

解法

layout畫面的區塊

views/layouts/application.html.erb
<html>
...(中間省略)
<body>
  <%= render "common/navbar" %>
  <%= notice_message %>
  <!-- 主要顯示區塊 -->
  <%= yield %>  
  <%= render "common/footer" %>
  <!-- 我們把javascript整塊搬到這邊載入定義 -->
  <!-- 問題就在這邊!我們需要下面再擺放個區塊擺我們自訂的javascript -->
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
  <!-- 所以在這邊我們新增一塊自訂輸出,呼叫上面定義的javasctipt -->
  <%= yield :handwrite_javascript %>
</body>
</html>

view file setting

*.html.erb
<%= content_for :handwrite_javascript do %>
  <script>
    /*自訂的js在這*/
  </script>
<% end %>

(我們的顯示內容在這)

可以參考這

 
almost 2 years ago
目前已知的兩個方法
<%= link_to( 'javascript:;', html_options={ class: "nav-scroll-bar",id: "empty_cart"}) do %>
  購物籃 <%=fa_icon "shopping-basket" %> <span class="badge">0</span>
<% end %>

<%= content_tag :a,class: "nav-scroll-bar",id: "empty_cart" do %>
  購物籃 <%=fa_icon "shopping-basket" %> <span class="badge">0</span>
<% end %>
 
almost 2 years ago

ERB-snippets的功能是在編輯erb檔案時,能夠更方便地給予標籤,少打很多字。
傳送門

常用的對照表

Tab Trigger Output
er <% %>
pe <%= %>
pc <%# %>
if <% if %>...<% end %>
ife <% if %>...<% else %>...<% end %>
else <% else %>
elsif <% elsif %>
end <% end %>
lt <%= link_to ..., ... %>
each <% @things.each do /thing/ %> ... <% end %>

而emmet這個plugin更是強大,網路上也有多很教學,在這就不贅述了。
我參考的教學 在這

兩個共存

兩套plugin都安裝之後,我前面安裝的ERB-snippets就會失去效用。
例如:er + tab 輸出變成了 <er><er>
參考解法
"disabled_single_snippet_for_scopes": "text.html, er, pe, pc, if, ife, else, elsif, end, lt, each"
把上面這行加到 Perferences/Settings-User之後,重開即可。

 
almost 2 years ago


案發現場敘述

在assets裡的js檔想要使用xxx_pathxxx_url給路徑時會發生錯誤,不然就是使用root_url給的是本機資料夾的路徑。

事故原因

這個地方本來就沒有內建url_helpers,發生錯誤不能用是很正常的。

解法

在要跑url_helpers的js檔案內加上<% self.class.include Rails.application.routes.url_helpers %>,它就能夠使用了。但是!若使用到xxx_url還是會發生錯誤,是因為在assets的機制中,它會先把資料先打包整理好,這當中它沒有辦法知道系統預設的路徑,所以這時候我們就得要routes.rb內手動加上預設的路徑(以我使用localhost:3000為例):default_url_options host: "localhost:3000"

蠢點

到頭來還是要自己設定路徑,那一開始就直接在js檔案中設定路徑就好啦!不過改js檔跟routes比起來還是有差(爽度不一樣),在之後也許會學到更進階的應用也說不定。

 
almost 2 years ago

我為何要做

記得一個不錯的比喻提到,給網站包裝就像面試要穿衣服一樣,別裸奔就出去見人啊~所以,要把自己的網站demo給別人看之前,總是要替網站穿個衣服,最好用Landing page來包裝一下啊~
所以,我就在 網路上挑選了一個喜歡的樣板,把它套到自己的網站上當landing page,順便了解前端的一些操作,包括rails assets的一些使用方法。這篇就是紀錄我整個套板解雷的過程。

正文開始

找到並下載喜歡的樣板

我是到startbootstrap內,挑選到自己喜歡的樣式並下載,而我上圖中是修改自這款Agency

把它塞進rails view

解壓縮檔案後,我們把index.html的body中整塊複製貼到我們rails的view當中,接下來就要搞定三個部分:stylesheets、javascripts、images。

stylesheets


上面截圖link的部分,我們知道它link進來的"順序"。

  1. Bootstrap,這部分用rails gem bootstrap-sass
  2. agency,要把它放到我們assets/stylesheets的路徑下,還要把它import進來。
  3. font-awesome,這部分有rails gem font-awesome-rails代替。
  4. google-fonts,外部的字型連結就不用管它了。
app/assets/stylesheets/application.css.scss
/*
 *= require_tree .
 *= require_self
 */
@import "bootstrap";

@import "bootstrap-sprockets";

@import "landing/agency";

@import "font-awesome";

我agency.css放置的路徑在app/assets/stylesheets/landing/
要注意!這import的順序會有影響,但影響在哪?
下圖左:把agency擺到bootstrap上面,部分格式就跑掉了。


這部分被順序影響,是因為它們在某些格式的設定有重複的情況,後者會覆蓋掉前者。
這邊弄好,基本上畫面的格式就完成了,只剩動態的畫面以及圖片都找不到。

javascripts



這邊有load一個jquery-easing,我用rails gem jquery-easing-rails
把一些要load進來的js全部丟到javascripts的目錄下即可,這邊比較不會有像css有重複定義的問題。

app/assets/javascripts/application.js
//= require jquery
//= require bootstrap-sprockets
//= require jquery_ujs
//= require jquery.easing
//= require turbolinks
//= require_tree .

images

上面兩個步驟完成後,接著就是把圖片整組複製到assets/images目錄下,最後就是換掉view裡面的連結:
例如使用來替代原本的img tag:<%= image_tag "landing/portfolio/roundicons-free.png",class: "img-responsive" %>


這也有一個地方要注意!就是藏在css裡面的圖片路徑也要記得換掉,agency.css當中就有兩個圖片要更改路徑:我把agency.css改成agency.css.erb,讓它也能使用image_tag來更換路徑。

layout

我把landing page與我們一般的頁面分開,並把外部的一些link也都補進來,例如google-fonts的部分。

app/controllers/pages_controller.rb
class PagesController < ApplicationController
    layout 'landing',only: :landing
  def index
  end
  def landing
  end
end
app/views/layouts/landing.html.erb
<!DOCTYPE html>
<html>
<head>
  <title>Bro.tw |</title>
  <%= csrf_meta_tags %>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
  <link href='https://fonts.googleapis.com/css?family=Montserrat:400,700' rel="stylesheet" type="text/css">
  <link href='https://fonts.googleapis.com/css?family=Kaushan+Script' rel='stylesheet' type='text/css'>
  <link href='https://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
  <link href='https://fonts.googleapis.com/css?family=Roboto+Slab:400,100,300,700' rel='stylesheet' type='text/css'>
  <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
  <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
  <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
    <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
  <![endif]-->

</head>
<body id="page-top" class="index">
<%= yield %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
</body>
</html>

心得

開始到完成,會發現整個過程不是很難,但其實剛開始解壓縮跑出一堆檔案我有被嚇到。想說它為什麼有這麼多檔案,但開始把它抓進來用,便發現沒有那麼多檔案需要用,檔案中大都是備份的檔案,真正需要的就是css,js,img的部分。在修改assets/stylesheets時,才知道import的順序會有影響,原先都是讓它自己抓根目錄下面的css,但畫面長得不一樣,後來強制使用import來給它順序,結果才正確。最後,在修改圖片路徑的部分,也很容易miss掉放在css檔案中的路徑,透過修改路徑的過程中才知道可以把css改成css.erb用helper給它路徑。

 
almost 2 years ago

自己給自己出的題目:
基本購物車的結構與動作

function total(array) { //加總用的function

    return array.reduce(function(a, b) {
        return a + b;
        //reduce預設會把這列內的第一個值和執行後return的值塞回第一個變數a

        //並取下一個值為第二個變數b

    });
}

function product(product_name, price, quantity) { //產品的結構

    this.name = product_name; //產品名稱

    this.price = price; //產品價錢

    this.quantity = quantity; //產品數量

    this.clone = function() { //定義clone function

        return Object.assign({}, this); //回傳本身這個物件

    };
    this.set = function(attribute,value) {//設定值

        this[attribute] =value;
    };
}
var myhome = {//設定一個倉庫,存放產品

    product: [],
    pushin: function(product) {//把產品放入的動作

        this.product.push(product)
    },
    show: function() {//把倉庫內的產品列出

        this.product.forEach(function(pro) {
            console.log("[", pro.name, "][", pro.price, "][", pro.quantity, "]")
        });//forEach就是把陣列內的值一個個取出來後並個別執行動作

    },
    find: function(product){//回傳產品名稱為product的array id

        for (var i in this.product)
            if (this.product[i].name==product)return i;
        return -1;
        //這部分可以改善結構改為name:{apple,lemon},price:{100,50},這種模式就可用indexOf來找

        //目前不清楚這部分效能上的差異。

    }
};
var cart = {//設定一個購物車,放置想買的產品清單

    items: [],//產品

    total: 0,//總金額

    pushin: function(from,item, quantity) {//把倉庫內的某產品放入購物車

        var product_id=from.find(item);//要先確定倉庫內有該產品

        if (product_id > -1){//id小於-1代表沒找到

            product=from.product[product_id];//有找到的話把該產品讀出

            this.items.push({//把產品的內容資訊塞入購物車

                name: product.name,//名字

                price: product.price,//價錢

                quantity: quantity,//放進購物車的數量

                subtotal: product.price * quantity//小計一下

            });
            this.update();//更新總價,funciton在下方

        }else{console.log("倉庫內沒有",item);}
    },
    update: function() {//更新總價

        var subtotal_array = [];//用陣列把每個產品的小計都放進去

        this.items.forEach(function(product) {
            subtotal_array.push(product.subtotal)
        });
        this.total = total(subtotal_array);//加總

    },
    show: function() {//跟同上,把購物車內的資料列出

        this.items.forEach(function(item) {
            console.log("[", item.name, "][", item.price, "][", item.quantity, "][", item.subtotal, "]")
        });
    },
    find: function(item){//找購物車內的產品,要異動購物車產品時會用到,目前沒用

        for (var i in this.items)
            if (this.items[i].name==item)return i;
        return -1;
    }
};

apple = new product("apple", 100, 9527);//建立一個產品

lemon = apple.clone();//複製一個產品

lemon.set("name","lemon");//為產品改名字

lemon.set("price","26");//為產品改價錢

console.log(lemon);//Object {name: "lemon", price: "26", quantity: 9527}

orange = new product("orange", 50, 689);//再定義一個產品

myhome.pushin(apple);//塞入蘋果至倉庫

myhome.pushin(orange);//塞入橘子至倉庫

myhome.show();//列出倉庫內所有產品

//[apple][100][9527]

//[orange][50][689]

cart.pushin(myhome,"apple", 3);//從倉庫找蘋果進購物車

cart.pushin(myhome,"orange", 2);//從倉庫找橘子進購物車

cart.pushin(myhome,"lemon", 1);//倉庫內沒有檸檬

console.log(cart.total);//400

cart.show();
//[apple][100][3][300]

//[orange][50][2][100]

myhome.pushin(lemon);//把檸檬也放進倉庫

cart.pushin(myhome,"lemon", 1);//從倉庫找檸檬進購物車

console.log(cart.total);//426

心得


(圖為lativ購物車的畫面)
練習做這個的目的,是想要減少一些操作進入後端,例如想要為產品的訂購數量+-1時,要即時計算金額,更甚至直接將購物車的結構放在user的cookie當中,不用放在server db內。過程中也發現功能越想越多,越來越混亂,果然這在事先要有一定程度的規劃,儘管是小作品也需要!

20160307自己補充

使用AngularJS的ng-model即可解決!
http://output.jsbin.com/zagoyovuke/

  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
  <div ng-app>
    <p>toy.price: <input type="number" ng-model="toy.price" ng-init="toy.price=199"></p>
    <p>toy.quantity: <input type="number" ng-model="toy.quantity" ng-init="toy.quantity=5"></p>
    <p ng-bind-template="{{toy}}"></p>
    <p ng-bind-template="total:{{toy.price*toy.quantity | currency}}"></p>
  </div>
 
almost 2 years ago

登入帳號
heroku login

建立app並直接取名
heroku create app名字

把app改名
heroku apps:rename --app app名字 新名字

把app刪除
heroku apps:destroy --app app名字

查看app參數設定
heroku config --app app名字

--app app名字可以縮寫為 -a app名字,用途為指定某個heroku app
若已在該app的目錄下,大部分指令可省略此參數(目前我已知是刪除app不能省)。

把pc內heroku套件刪光光(警慎使用)

gem uninstall heroku --all
rm -rf /usr/local/heroku
rm -rf ~/.heroku
 
almost 2 years ago

我的學習背景

替代役服役中,大學及研究所都是唸電子系,跟網站一點關係都沒有,唯一有接觸的部分只有因為「興趣」,接了幾個打工的case做做簡單的網站(現在回過頭來看,之前做的網站跟渣一樣啊啊啊)。結束學業後,在服役的這段時間內,也決定了自己未來想靠網站來謀生。

那個人

在知道有這堂課之前就常常在臉書上關注XDite,看她分享開發的技術以及growth相關的知識(還有美食文?),讓我提起興趣深入下去學習Rails這個框架。已經自修一陣子了後,也發現學習曲線慢慢降低,欠缺一個爆炸性成長,帶我進入另外一個小宇宙。這時候又剛好看到開課訊息,心想,那既然想要拜師學Rails,當然要找武林中最厲害的,就這麼巧,XDite就剛好是那個人。

上課前


從報名後的每個禮拜都收到討債信,要求一定要去練習Rails101,為了充分發揮這堂課的價值,我也反覆練習Rails101 許多遍,熟習整個流程、步驟及錯誤訊息的排除。現在也很慶幸有花這段時間練習,在課程高度密集的情況下,還要花時間排除錯誤真的會很頭大,不過,實在也是不用太擔心,遇到問題有助教,不敢提問有Slack,真的不行還有課後輔導,全方位的教學啊!

課堂上

七點鐘上課並提供便當,這真的是讓我覺得太貼心了,下班搭車過去也不用急著去找買晚餐吃,不會餓肚子上課(營養滿分而且還有點撐),場地也很舒適。上課的方向,就朝著建構購物車網站的前進,金流、寄信、部署上線等關卡各個擊破,step by step保證不卡關。

  • 第一週的重點在於使用User story做購物車網站的規劃,其實這部分感覺起來是滿簡單的,但在課堂練習時,才發現自己要去規劃一個網站的時候,想要做的功能跟實際上的需求好像會有點打架,這部分還需要多點經驗累積啊…其他的內容就在Rails101上的有實作過,難度不高,下課後的作業也還在我自修的範圍內,難度也不高。
  • 第二週,依照上週的user story規劃把整個購物車網站的功能各個擊破,不得不說,這週真的超級精實超級硬,還好我前一週有偷跑偷做一點,才不至於太混亂。說實話,我自修了快半年,這兩週的密集的課程內容就已經超越我自己慢慢摸索實作的部分了。更不用說回家作業了…課程設計兩個禮拜給你做。
  • 第三週,金流、寄信、部署上線這些網商必備的功能都被在這週被拆解完畢,看著自己做的網站從零到現在能夠線上刷卡完成,真的是莫名的感動啊~另外,還有講解如何整理包裝自己的程式碼,我真的非常喜歡這部份,把程式寫的舒服、好理解,遇到問題也比較好解決。

最後

一定要空下時間來寫作業!作業,又是另外一段副本!自己當自己的老師,想辦法找出答案並把它表達編輯在QUIP,增加信心、加強印象,另外,同學們的作業也是很好的參考來源!我甚至還預習操作了下次上課的進度,有什麼問題也好在當場提出!課前的準備、課堂上的學習、下課後的作業都是非常好的體驗。有決心想密集學習、快速上手Rails的你可以試試!

 
almost 2 years ago


上圖是我和陳義達通電話後寫給他的user story
下圖在通電話前他傳給我的"東西"要我幫他做個網站,我也好當作練習的作品。
老實說圖片畫成這樣我根本看不懂啊!
所以才產生了user story讓我們雙方都好理解這網站設計的需求。

自己稍微修正後:

陳義達想在網站上做簡單的進銷存:
    他要在首頁上能夠看到目前剩下的原料存貨,用來判斷是否有哪些原料需要進貨
        要看到存貨的顯示格式為:品名、數量、單位
    他想要在首頁上能夠進行賣產品的動作,在後台能夠進行進貨的動作
        要在後台能夠建立產品,並可以建立它對應的原料
        進貨、銷貨都要有紀錄,要列表
        銷貨的流程要藉由自訂的產品及數量來減少相對應的原料
            銷貨的流程要能夠選取多樣產品
            賣出產品後要減少這次產品相對應的所有用料
    他要在後台有個別的列表能看到進貨及賣產品的清單
        要在後台有個清單同時列出進貨銷貨的

接著說說我在Rails上是如何實作:

建立產品及庫存關聯

  1. 看到原料及產品,首先新增了三個model:Material、Product、ProductMaterial,並建立關聯。
    • Material:name、quantity、unit_name,存原料的名稱、數量、單位名稱。
      • has_many :product_materials
    • Product:name,存產品名稱。
      • has_many :product_materials
      • has_many :items,through: :product_materials,source: :material
    • ProductMaterial:product_id、material_id、quantity,存產品與原料的數量關係。
      • belongs_to :product
      • belongs_to :material
  2. 建立controller:Materials、Products,原料及產品的「顯示、新增、修改、刪除」。
    • nested_form gem來新增產品的多個原料。
      • accepts_nested_attributes_for :product_materials
      • 產品要選擇原料時,select option使用原料名稱,而value是material_id:
        • <%= t.select :material_id,materials.collect {|p| [ p.name, p.id ] } =%>
      • nested_form的用法會在整理之後補上
  3. 建立個controller:pages,來當首頁,可以看到原料資訊。

建立進貨銷貨動作
思考:銷貨要去撈產品還要計算減掉多少原料,而進貨動作只要異動原料,比較簡單,先做!

  1. 所以我新增兩個model:Buylist、BuylistMaterial,當做進貨單。
    • Buylist:單純當作進貨單,沒有額外新增欄位。
      • has_many :buylist_materials
    • BuylistMaterial:buylist_id、material_id、quantity,存進貨單與原料的數量關係。
      • belongs_to :buylist
      • belongs_to :material
  2. 建立controller:buylists,進貨單的「新增」。
    • 和建立產品一樣,用nested_form新增多個原料及數量,只差在最後要去異動原料數量。
  3. 進貨的部分完成,基本上建立銷貨單的和進貨單的步驟都一樣:
    • 新增model:Salelist、SalelistProduct,當作銷貨單及銷貨的產品內容。
    • 建立controller:salelists,銷貨單的「新增」。
      • 在計算要扣除的原料數量時會有兩層,銷貨單的產品數量*產品的原料數量。

歷史清單
想法:最後我要有個統整的清單把進貨銷貨都紀錄到model,但我要分辨進貨與銷貨。

  1. 建立一個model:History,只要每次進貨或銷貨都會對這個model做儲存。
    • History:type_id、list_id,type_id用來指出存貨或銷貨,list_id就是存貨單或者銷貨單的id。
    • 這部分我使用after_create在兩個model中(buylist、salelist)來對history做新增資料。
  2. 完成了。

後記:

過程中發現進貨及銷貨是不給修改的。若不想要對原料直接進行修改,要能在新增訂單的同時做訂單內產品或原料的備份功能,因為可能在過程中會有產品的異動或者許多意想不到的狀況發生,有備份的功能比較有可能做倒退修正,或許根本不會有這種情況發生,這就要回過頭來問問使用者在某操作場景下會有怎樣的操作模式,要去瞭解使用者的情況並寫在user story中,即減少雙方的疑慮。

20160315更新

polymorphic association
多態分配,history >> buylist & salelist
https://rocodev.gitbooks.io/rails-102/content/chapter1-mvc/m/polymorphic_assoiciaion.html

 
almost 2 years ago


參考來源

第四章重點整理-2:物件、陣列

說明:所有程式碼都是我看著上面這本電子書的教材經過實際操作並修正為最適合我自己吸收的程式碼,如果有有緣人發現問題,可以回報給我知道哦哦哦!我會非常感謝您!

物件的讀寫
var BigData={};
var map_to_array=function(name,data){
  BigData[name]=data;//寫入物件

};
var GenerateData=function(str_array){
  for (i=0;i<str_array.length;i++)
    map_to_array(str_array[i],Math.random());//創建資料,Math.random()給予亂數

};
GenerateData(["A","B","C","D"]);
console.log(BigData);//Object{A:...,B:...}

var print_array=function(ary){
  for(var i in ary)
    console.log(i,">>",ary[i]);//讀出物件資料

}
print_array(BigData);//A >> ... , B >> ...
陣列的讀寫
var todoList = ["work1"];
todoList.push("work2","work3","work4");//從陣列末筆資料塞入

console.log(todoList);//["work1", "work2", "work3", "work4"]

console.log(todoList.shift());//work1,取出第一筆並送出

console.log(todoList);//["work2", "work3", "work4"]

console.log(todoList.pop());//work4,取出最末筆並送出

console.log(todoList);//["work2", "work3"]

todoList.unshift("Work!!!");//從陣列第一筆資料塞入

console.log(todoList);//["Work!!!", "work2", "work3"]

todoList.push(...todoList);
//"..."意思是把陣列內的值分開讀,否則是一包array push進去

console.log(todoList);//["Work!!!", "work2", "work3","Work!!!", "work2", "work3"]

console.log(todoList.indexOf("work2"));//1,抓第一筆match的資料

console.log(todoList.lastIndexOf("work2"));//4,抓最後一筆match的資料

console.log(todoList.slice(4));//["work2", "work3"],從第四筆開始抓

console.log(todoList.slice(1,4));//["work2", "work3","Work!!!"],從第一筆抓到第四筆"之前"

console.log([...["a","b","c"],...["d","e"]]);//["a", "b", "c", "d", "e"]
用陣列的串接來刪除其中一筆
function del(str,target){
  return str.slice(0,target)+str.slice(target+1);//"+"可以改成".concat"

//return str.slice(0,target).concat(str.slice(target+1));

}
var word="123abc";
console.log(del(word,4));//123ac,陣列的第五筆資料是"b"
字串的串接及使用
var str="abc123"
console.log(str.length);//6

str.myproperty=999;
console.log(str.myproperty);//undefined,非object無法自定義屬性喔

console.log(str.slice(4));//23,從第五個字開始抓

console.log(str.indexOf(1));//3,"1"是第四個字

console.log(str.charAt(3));//1,第四個字是"1"

console.log(str[3]);//1,第四個字是"1"

console.log(" \n 123  \n".trim());//123,把空白及一些字符清除
物件參數
var val="這是全域變數";
function test(){
  console.log(arguments);
  console.log(arguments.length);
  console.log(window.val);//全域變數

}
test(["abc","cba"],123,{name:"brohand",age:"18"},function(a,b,c){return a+b+c;});
//[Array[2], 123, Object, function],4,這是全域變數
範圍加總
function range(start,end,num){
  num=num||1;
  if ((end-start)/num < 0)
    return "ERROR!!!"//check一些有誤的case

  var result=[];
  for(var i=start;start<end?i<=end:i>=end;i+=num)
    result.push(i);
  return result;
}
function sum(array){
  var sum=0;
  for(var i in array)
    sum+=array[i];    
  return sum;
}
console.log(range(1, 10));//[1,2,3,4,5,6,7,8,9,10]

console.log(range(5, 2, -1));//[5,4,3,2]

console.log(range(1, 10,-1));//ERROR!!!

console.log(range(1, 10,2));//[1,3,5,7,9]

console.log(sum(range(1, 10)));//55
陣列轉置
function invers(array){
  var length=array.length;
  var result=[];
  for(var i in array)
    result.push(array[length-1-i]);
  return result;
}
console.log(invers(["A", "B", "C"]));//["C", "B", "A"];

console.log(invers([1, 2, 3, 4, 5]));//[5, 4, 3, 2, 1]
物件串接操作
function array2list(array){
  var result=null;//先定義最後一筆

  for(var i=array.length-1;i>=0;i--){//反向定義物件

    result = subobject(array[i],result);//重新打包物件

  }
  return result;
};
function subobject(val,rest){打包物件
  return {value: val, rest: rest};
}
function list2array(obj){//迴圈解開全部的list

  var result=[];
  for (var node=obj;node;node=node.rest)
    result.push(node.value);
  return result;
}
function find_form_list(list,target){//用遞迴的方式抓某值

  if (!list)
    return undefined;
  else if(target==0)
    return list.value;
  else
    return find_form_list(list.rest,target-1);
 // return list2array(list).slice(target,target+count);

}
var list=array2list([10,20,30]);
console.log(list);//{value:10,rest:{value:20,rest:{value:30,rest:null}}}

console.log(list2array(list));//[10,20,30]

console.log(find_form_list(list,2));//20

console.log(subobject(50, subobject(70, null)));//{value: 50,rest:{value:70,rest:null}}
兩個物件深度比較
function deepComp(obj1,obj2){
  if (obj1===obj2){return true;}//

  function comp(o1,o2){
    if(!o1 || !o2){return false;}//判斷有無null出現,一個有值一個沒值。

    if(o1.length!= o2.length){return false;}//一般陣列矩陣長度判斷,object長度為undefined

    if(typeof o1 != typeof o2){return false;}
    if(typeof o1 == "object"){//同為object,進行特別判斷

      if(Object.keys(o1).length!=Object.keys(o2).length){return false;}//物件判斷長度專用

      for(var i in o1)//深入進去object判斷內部

        return comp(o1[i],o2[i]);
    }
    else{
      return o1==o2;//如果不是object就直接判斷吧

    }
  }
  return comp(obj1,obj2);
}
var obj = {here: {is: "an"}, object: 2};
console.log(deepComp(obj, obj));//true,全部長一樣

console.log(deepComp(obj, {here: 1, object: 2}));//false,object裡面東西長不一樣

console.log(deepComp(obj, {here: {is: "an"}, object: 2}));//true,長一樣

console.log(deepComp(obj, {here: {is: "an"}, object: 2, a:3 }));//false,object裡面的東西不一樣