rails strong parametersの使い方とハマったところ

基本的なつかい方

送信する方はとりあえずjqueryでこんなイメージ

$.ajax({
  type: "POST",
  url: "https://example.com/books",
  data: JSON.stringify({
    title: 'タイトル',
    description: '説明'
  }),
  contentType: 'application/JSON'
});

今回使うテーブルはbooksでtitleとdescriptionカラムをもつ。modelはこんな感じ

class Book < ApplicationRecord
  validates :title, presence: true
  validates :description, presence: true
end

コントローラ

class BooksController < ApplicationController
  def create
    Book.create!(book_params)
    head :created
  rescue ActionController::UnpermittedParameters => e
    head :bad_request
  rescue StandardError => e
    head :internal_server_error
  end

  private
    def book_params
      params.require(:book).permit(:title, :description)
    end
end

ハマったところ

wrap_parameters

postで送信すると、送信したデータがparamsにcontroller名のハッシュとしてセットされる。例えば、/path/to/booksというURLに{ title:'タイトル', description: '説明' }をjson形式でpostするとparams[:book]とうハッシュにセットされる。json形式でなく、postするとそのままparams[:title]、params[:description]がセットされる。これは、wrap_parametersという機能らしくrailsのデフォルトの設定のままだとこのようになる。

requireの中のpermitで指定してない項目があってもエラーにならない

例えば上記の例で{ title:'タイトル', description:'説明', hoge:'ほげ' }みたいなデータを送信するとUnpermittedParametersがraiseされると思っていた。が、実際にはraiseされない。ただし、json形式でない形で送信した場合にrequireせずに以下のようなコードを書くとhogeは許可されていないのでUnpermittedParametersがraiseされる。

def book_params
  params.permit(:title, :description)
end
paramsにformatが自動で付与される

jsonで送信するとparams[:format]='json'という値が勝手にセットされて以下のようなエラーが出る。勝手につけたパラメータでエラーになるってよくわからないが、require(:book)みたいな使い方をされる前提なのかもしれない。

found unpermitted parameters: :format
パラメータ名がmodelと同じだとparamsの中身がフィルタリングされる

以下のプログラムにして{ title:'タイトル', description:'説明', hoge:'ほげ' }というデータを送信。permitに:hogeを追加したのにbook_paramsの中身には:hogeがなくなってる。

def create
  book_params ## book_params -> { title:'タイトル', description:'説明' }
  ・・・
end                                                                                                                                                                                                                                           
 
private
  def book_params
    params.require(:book).permit(:title, :description, :hoge)
  end

ちなみにbooksモデルを削除して実行したらbook_paramsに:hogeはちゃんといた。ちゃんとmodelと連携までしてるのか。裏で色々やってくれてるのでわからなくなる、、
わかりずらい文章だが、以上です

git merge用ブランチを作成してコンフリクトを回避する

困ったこと

branchAとbranchBがあって、branchBからfeatureブランチを作成。featureブランチで修正を加えてorigin/branchAにマージしようとしたらfeatureでまったくいじってない部分でコンフリクト。featureの修正だけorigin/branchAに取り込みたい。

解決策
$ git checkout feature
$ git log --oneline とかでマージしたいコミット番号確認
$ git checkout branchA
$ git checkout -b feature_merge
$ git cherry-pick featureのコミット番号
$ git push origin feature_merge:feature_merge

リモートで以下を行えばそれぞれ修正分だけをマージできる
origin/feature_merge -> origin/branchA のマージ
origin/feature → origin/branchBのマージ

以上です

flutter Scaffoldで使えるWidget

Scaffoldで使えるWidgetを指定してみた。Scaffold使うと以下を簡単に指定できるのか
・appBar : 画面上のバー
・drawer : Drawerメニュー。指定するとappBarの左に勝手にメニューアイコンが表示された
・endDrawer : drawerと同じだけどappBarの右にメニュー表示して右から表示される
・floatingActionButton
・bottomNavigationBar
・bottomSheet : iOSのアクションシートみたいなやつ.これはあとで試す

イメージ

f:id:yoppy0066:20190623141230p:plain:w320

実装
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'MaterialApp Title',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(title: Text("AppBar")),
        drawer: Drawer(
          child: Center(child: Text("drawer"),)
        ),
        endDrawer: Drawer(
            child: Center(child: Text("endDrawer"),)
        ),
        body: Center(child: Text("Hello")),
        floatingActionButton: FloatingActionButton.extended(
          label: Text("floatingActionButton"),
          icon: Icon(Icons.add),
        ),
        persistentFooterButtons: <Widget>[
          Text("persistentFooterButtons"),
          IconButton(icon: new Icon(Icons.timer)),
          IconButton(icon: new Icon(Icons.people)),
        ],
        bottomNavigationBar: BottomAppBar(
          child: Container(
            height: 50,
            child: Center(
              child: Text("BottomAppBar"),
            ),
          ),
        ),
      )
    );
  }
}
Drawerイメージ

f:id:yoppy0066:20190623141256p:plain:w320

以上です

ionic1 iosでunsafeエラーで画像が表示されないときの対応

またionic1。ionic-cli5.0.2でtabsのテンプレートプロジェクトを作成後、iPhoneでアプリを起動すると画像が表示されない。safariの開発モードで見るとこんなエラーが出てた

unsafe://ionic/localhost/img/adam.jpg

$compileProvider.imgSrcSanitizationWhitelistでサニタイズを無効化したら表示された

app.js

.config(function(
  $stateProvider,
  $urlRouterProvider,
  $compileProvider
) {

  ・・・

  // 画像のサニタイズ無効化
  $compileProvider.imgSrcSanitizationWhitelist(/^\s*((https?|ionic):)/);
};

ちなみにcordova-plugin-ionic-webviewのバージョンは4.1.0と現時点の最新でした。以上です

ionic1 ion-slidesのスワイプでのページ切り替えを無効化する

今さらすぎて誰の役にも立たない内容だけど、ハマったのでメモしておく。今だにionic1使ってるプロジェクトあるから仕方ない。ionicではswiperというのを使ってるらしくswiperのドキュメントみたら解決した。

swiperのドキュメントはこちら
https://idangero.us/swiper/api/

ドキュメントに「noSwiping」というオプションがあって、これをfalseにすると「noSwipingClass」で指定されているクラスの要素のスワイプ を無効にしてくれるらしい。で、「noSwipingClass」のデフォルトが「swiper-no-swiping」らしい。

<ion-slides class="swiper-no-swiping" ...>                                                                                                                                                                                                    
・・・                                                                                                                                                                                                                                        
</ion-slides>

以上です

swift codableのデバッグ

型や項目の必須、任意が正しくないと1件もヒットしなくなってしまうのでエラー時のデバックプリントはたぶん必須

Swift

        let data = """
[{
    "id": 1,
    "name": "USER1",
},{
    "id": 2,
    "namexxx": "USER2",
}]
""".data(using: .utf8)!

        struct User: Codable {
            var id: Int
            var name: String
        }

        do {
            let users = try JSONDecoder().decode([User].self, from: data)
            dump(users)
        } catch {
            print(error)
        }
    }

コンソール

keyNotFound(CodingKeys(stringValue: "name", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 1", intValue: 1)], debugDescription: "No value associated with key CodingKeys(stringValue: \"name\", intVal\
ue: nil) (\"name\").", underlyingError: nil))

の結果より、Index = 1がkeyNotFoundとなっているので2番目のデータがおかしいことがわかる。以上です。