Rails GoogleのAPIで表示したデータを保存する
APIのデータは取得した型でそのままコントローラに送るとエラーになります。
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の表示なども引数をクロージャーで渡す。
クロージャーは、引数として利用することが多いと思う。