Rails GoogleのAPIで表示したデータを保存する

APIのデータは取得した型でそのままコントローラに送るとエラーになります。

f:id:happy_teeth_ago:20180614122754p:plain

nilが渡ってしまう。

リンクしたときに、DBに保存したい。

createを呼ぶべき。createはpostなので、formを利用しないといけない。

<div class="w3-row-padding w3-padding-16 w3-center">
<%= @books.each do |book| %> <//ここでもらった仮引数を詰め込みます。
<%= form_for(book) do |f| %>

<div class="w3-quarter">
<%= book.title %>
<%= book.author %>
<%= book.publish %>
<%= book.published %>
<%= link_to image_tag("#{book.image_link}"),
new_book_path(book) %>
<%= f.hidden_field :title %>
<%= f.hidden_field :author %>
<%= f.hidden_field :publish %>
<%= f.hidden_field :published %>
<%= f.hidden_field :image_link %>

<i class="fas fa-pencil-alt"><%= f.submit value="シェアする"%></i>
</div>
<% end %>
<% end %>
</div>

formタグは、hiddenにできます。とりあえずformタグを利用することが大切。

DBに保存する必要はないです。indexは取得するだけなので、

eachともちろん併用できます。each文の中で回さないと意味がないです。仮引数でループ回していくので。

 

標準のscafforldingを見て参照すると良い。//=>大切です。

_from.html.erbを参照する。 

そこには、このように記載してあります。

<%= form_with(model: book, local: true) do |f| %>

 formを回しなさいということですね。

 

form_forを確認すると、

form_for(モデルオブジェクト [, オプション]) do |f|
end

第1引数はオブジェクト名、第2引数は?

モデルにオブジェクトが入っていれば、それを保存するというのがfromの仕様になっているよう。なので、値を入れておかないといけない。

@booksに入っているのがGoogleAPIの型になっている。

 これが1番の問題。

これを解決するために、取得したあと、DBに書き込まずにモデルだけ作るのはどうか?。行けそうである。

mapを利用する。一度に変換してしまう。

なんて素晴らしいmap!

すべてがオブジェクトのRubyも素晴らしい!

 

def index
@books = GoogleBooks.search(params[:search],{:count => 20}).map{|googlebook| book = Book.new
book.title = googlebook.title
book.author = googlebook.authors
book.publish = googlebook.publisher
book.published = googlebook.published_date
book.image_link = googlebook.image_link
book
}
end

一度mapの中で変数に入れないといけない。仮引数をgoogleBookにします。

Book.newはスタティックな値なので大文字。

あとは値を詰め込むだけ。

mapの中で返却しないといけない。

なのでbookは必要です。

ストロングパラメータでないと、ハッシュは詰め込めないので、別途ストロングパラメータを設定しておく。

 

ポイントは

1-GoogleBookのモデルを、ActiveRecordの型でオブジェクト作り直しました。

もうオブジェクト作ったので、formも簡単に作れます!

2-createはpost。そのためには、formが必要なのでformを作成しました。

 

 

 

Ruby (Rails) ハッシュのキー書き方まとめ 忘備録

ハッシュの書き方をまとめておきますね。

railsでよくある

params[:id]

これはなんなのか?

 

Railsで使われるparamsとう変数のidというkeyにアクセスしているのです。

そして、これは多くは、Railsでは、Viewからコントローラへ値を渡すときに用いられます。

 

まず基本のハッシュの書き方から説明しますね。

配列は

str = [1,3,5,6]

というふうに値が一つづつ入っていますね。

これをキーと値というもので2つ一組でセットで入っているものがハッシュといいます。

便利ですね。配列は[ ] で要素を囲みますが、ハッシュは{ } で要素を囲みます。

 

str = {"name" => "Ichiro", "age" => 28}

nameにはIchiro ageには28があります。

これが全体として、一つの値なので一つの変数 strに詰め込むことができます。

 

アクセスするときにはキーを指定します。

 

str["name"]  // => Ichiro が取得できます

 

ハッシュはすべて文字列になるのでそこだけ注意!

 

でもって

ハッシュの書き方の続きです。

{"name" => "Ichiro", "age" => 28}

このハッシュは

シンボルというものを利用してこのようにも欠けます。

シンボルは :コロンを利用した書き方の事です。

 

{:name => "Ichiro", :age => 28}

 

ただ""を:に置き換えただけですね。

でも""で囲まななくていいので、書くのは楽です。

さらに

 

{name: "Ichiro", age: 28}

 

コロンをキーの後ろに持ってくると =>も省略できます。

これは楽!!

だからこのように書くことが多いのです。

では、また

 

 

swift3 デリゲートメソッドの実装について

デリゲートメソッドをどのように実際に利用するか説明

呼び出し元    

 

//会話履歴テーブル,デリゲートで呼ぶ

var delegate: ConversationDelegate?

delegate?.ConversationSelected(Conversation: datMeeting!)

//datMeetingは実引数

 

 

// 会話履歴プロトコル

protocol ConversationDelegate {

    func ConversationSelected( Conversation: DatMeeting)    

}

 

//実装先 呼び出されている方

   func ConversationSelected(Conversation: DatMeeting) {

        //ここでdatperson id

        perName.text = datPerson.name

        //少配布物を作成

        distSmall.text = person.distSmall

        convCont.text = Conversation.content

    }

 

主に画面の左右に別れているときに利用した。

画面が変わると全部メモリでは落ちている。

そこで次の画面につなげる仕組みの一つがデリゲート。

 

他の例 これはデリゲートメソッドではないけど

Msperson画面が2つに割れているもの、詳細 MAP

  private weak var msPersonData: MsPersonDataPad!

 

  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        super.prepare(for: segue, sender: sender)

        if segue.destination is MsPersonDataPad {

            // Embeded segue 受信のタイミングで MsPersonData インスタンスを取得し

            // 編集モードとデータを設定しておく

            msPersonData = segue.destination as! MsPersonDataPad

            msPersonData.setupDatPerson(.New, datPerson: datPerson)

        }

    }

 

    /// 編集モードでのdatParson(訪問先データ)の運用を開始する

    ///

    /// .Empty又は.Newの場合、datPerson は nil(default)、datPerson != nil の場合は

    /// 指定 mode によらず.Existing になる。

    /// - Parameters:

    ///   - mode: 編集モード

    ///   - datPerson: 訪問先データ

    func setupDatPerson(_ mode: EditMode, datPerson: DatPerson? = nil) {

        self.editMode =

            datPerson != nil ? .Existing : mode == .New ? .New : .Empty

        datPersonImpl =

            self.editMode != .New ? datPerson : DatPerson.newFormalOne()

        // viewがすでに動作している(viewWillAppear <= state < dismiss)

        if canDisplyData {

            setDataOnUIs()

        }

    }

 

   /// 編集モードを表す

    ///

    /// - Empty: 該当無し(検索と訪問先の画面で検索結果が空,...等)

    /// - New: 新規登録

    /// - Existing: 既存訪問先(詳細表示と編集)

    enum EditMode: Int {

        case Empty

        case New

        case Existing

    }

 

 

SWIFT3 クロージャーについて

まずクロージャーについて

クロージャーとはなんなのか?

という質問について、まず

関数もクロージャーの一種である。

という説明がもっともわかりやすいと思われる。

関数は、処理をひとまとめにしたものだが、クロージャーより、詳細に設定できると考えると良い。

全く別物ではないのである。

基本形は

 

{ (引数名1:型,引数名2:型...) -> 戻り値の型 in 

クロージャーの実行時に実行される文

必要に応じてreturn で戻り値を返却

}

 

大外は{}で囲われる。inがポイントになるので赤字にした。

in キーワードで引数と処理が区別される。

 

関数と違い

クロージャーでは、外部引数名は利用できない。

デフォルト引数も利用できない。

通常のfuncに付け加えて利用できるものは、

簡略引数名が利用できる。 $0,$1など。$にインデックスをつけたものが利用される。

(例)関数

//2つの引数の和を戻す関数

func B(x:Int,y:Int)->Int{

    return x + y

}

print(B(x: 100, y: 500))

これが普通の関数

 

(例)クロージャー

var b = { (x:Int,y:Int) -> Int in return x + y}

print(b(200, 200))

こうなる

関数名がないので、他から呼び出しはできない。

 

//クロージャで型を宣言

var b_1 : (Int,Int) -> Int  //b_1はint型2つを引数に取るし、戻り値はint型を取りますということ

b_1 = { (x,y) -> Int in return x + y}

//{}がクロージャーで,x,yの引数を渡したら足し算して返すだけ

print(b_1(100,20))

 =>120

 

そもそも、なぜクロージャーがあるのか?

というと、関数を変数や、定数に代入したり、別の関数の引数に渡したりできるから。

これ大切ですね。

関数を変数、定数に代入するときは、関数名だけの式で関数を参照します。

 

 

関数内関数は禁止されています。エラーになります。

そこでクロージャーを利用します。

func aho (){

   func hoge(){

   }

}  //エラー

こんなふうに、関数内関数は利用できません。

でもクロージャーなら可能です。

(省略、想像してください。)

 

次に関数の引数となるクロージャーを関数として定義することを見てみてたい。

let aho = [1,2,3]

let doubleAho = aho.map{ $0 * 2 }

//aho配列の中から要素を一つ一つ取り出して$0に代入しようね。そしたら、それを2倍してね!ちなみにmap関数は配列に対して操作する関数です。こちらを参照ください。

doubleAho // [2,4,6]

 

関数をクロージャーとして扱う

func double(_ x: Int) -> Int{

    return x * 2

}

let aho = [1,2,3]

let ddoubleAho = aho.map(double)  //ここで関数をクロージャーとして呼び出しています

doubleAho // [2,4,6]

こうするとどのような操作をしているか、関数の中ではっきりと分かりますね。

 

 クロージャーを利用した変数、定数の初期化

クロージャーを利用すると何をしているかわかりやすい。

2次元配列を例に取る。//縦と横に配列がある、エクセルのような状態になっているもの。

var aho =[ [1,1,1],[1,1,1],[1,1,1] ]

aho => [ [1,1,1],[1,1,1],[1,1,1] ]

全部入力しているので、2次元配列を生成してみる

 

var aho = Array(repeating: Array(repeating: 1, count: 3), count: 3)

//ちなみにrepeatingとは配列を初期化するメソッド 

    ///     let fiveZs = Array(repeating: "Z", count: 5)

    ///     print(fiveZs)

    ///     // Prints "["Z", "Z", "Z", "Z", "Z"]"

    ///

    /// - Parameters:

    ///   - repeating 繰り返すべき要素

    ///   - count: 繰り返す回数、0以上

この中では1を入れて3回繰り返してね。

更にその外では、[1,1,1]をいれて3回繰り返してね

というメソッドである。

 

aho => [ [1,1,1],[1,1,1],[1,1,1] ]

 

これをクロージャで表現すると

var aho: [ [Int] ] = {

 let kurikaeshi_times = 3

 let low = Array(repeating: 1, count: kurikaeshi_times)

 let excel = Array(repeating: row, count: kurikaeshi_times

 return excel

}

aho => [ [1,1,1],[1,1,1],[1,1,1] ]

クロージャはわかりやすいですね。

 

補足するとクロージャーはコールバックとして利用されることが多いと思う。

非同期処理のためのDispatchモジュールはほとんど、コールバックを引数で受け取る。

MAPの表示なども引数をクロージャーで渡す。

クロージャーは、引数として利用することが多いと思う。