C#は三項演算子で暗黙の型変換してくれない

C#入門数日目なので温かい目で・・・:pray:

状況によって Container または Text を表示する、みたいなコードを書く際、 Flutterだと

Column(children: <Widget>[flag ? Container() : Text('some text')])

ができるけど、 C#

new Column(children: new List<Widget> { flag ? new Container() as Widget : new Text("some text") })

と、少なくともどちらか一方でも明示的にアップキャストしてあげないとならない。
勝手に Widget として解釈してくれない。

一方で

new Column(children: new List<Widget> { new Container(), new Text("some text") })

みたいにListの要素が型引数のサブクラスの場合は合法なので、
C#の型システムさんか三項演算子さんにはもう少し頑張っていただきたいと思いました

この挙動でちょっとこまったのは、

new RaisedButton(
    color: Palette.Primal,
    onPressed: isLoginPending
        ? null
        : () => { loginAttempt(this.email, this.password); })

みたいなボタンの実装。
FlutterやUIWidgetsでは、ボタンがenabledかどうかはコールバックがnullかどうかで判定されるのですが、

C#だと null() => {} の型が一致していなければならないらしく、nullを何かしらの型にキャストしてあげなければなりません。

new RaisedButton(
    color: Palette.Primal,
    onPressed: isLoginPending
        ? null as VoidCallback
        : () => { loginAttempt(this.email, this.password); })

正解はこれでした。 VoidCallbackにキャスト。

Unity UIWidgets アニメーションしない画面遷移

Navigator.push はデフォルトでアニメーションがありますが、
それをなくす方法 @ UIWidgets

Flutterだと

class NonAnimatingRoute<T> extends MaterialPageRoute<T> {
  NonAnimatingRoute({this.builder, this.settings})
      : super(builder: builder, settings: settings);

  final WidgetBuilder builder;
  final RouteSettings settings;

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation, Widget child) {
    return child;
  }
}

をどっかで定義して

Navigator.pushReplacement(
    context,
    NonAnimatingRoute<Null>(
        settings: const RouteSettings(name: '/init'),
        builder: (BuildContext context) => InitialPage()));

みたいな。

Unity UIWidgetsだと

public class NonAnimatingRoute : MaterialPageRoute
{
    public NonAnimatingRoute(
        WidgetBuilder builder = null,
        RouteSettings settings = null,
        bool maintainState = true,
        bool fullscreenDialog = false) :
        base(builder: builder, settings: settings, maintainState: maintainState,
            fullscreenDialog: fullscreenDialog)
    {
    }

    public override Widget buildTransitions(BuildContext context, Animation<float> animation,
        Animation<float> secondaryAnimation, Widget child)
    {
        return child;
    }
}

をどっかで定義して

Navigator.of(context).push(
    new NonAnimatingRoute(
        settings: new RouteSettings(name: "/init"),
        builder: (BuildContext context) => new InitView()));

みたいな。

UIWidgets、困ってもFlutterのコード資産をほぼそのまま使えるのがいいですね。笑

Unity UIWidgets 画面サイズにあわせてウィジェットのサイズを変更する

UnityのUIWidgets, 便利ですね。
ただ、Flutterでよく使われるような便利なパッケージが無いのが痛いところ。

FlutterならScreenUtilをインポートして脳死でパーツサイズを指定してマルチデバイス対応できましたが、
UIWidgetsだと自分でちょっとだけコードを書く必要があります。

private Widget _initialPanel()
{
    return new Container(color: Color.white, child: new Column(
        mainAxisSize: MainAxisSize.max,
        mainAxisAlignment: MainAxisAlignment.center,
        children: new List<Widget>
        {
            new MaterialButton(
                minWidth: 300 * MediaQuery.of(context).size.width / 750,
                height: 600 * MediaQuery.of(context).size.height / 1334,
                color: new Color(0xff00BE98),
                onPressed: () =>
                {
                    this.setState(()
                        =>
                    {
                        this.panelState = PanelState.BeforeLogin;
                    });
                }, child: new Text("ボタン", style: new TextStyle(color: Colors.white)))
        }
    ));
}

f:id:rnitta:20200210174713g:plain

height: 600 * MediaQuery.of(context).size.height / 1334,

1334x750 は僕が適当に決定したベースになるスマホの縦横比です。
グローバルな定数にしておくといいかもしれません。(そしてCanvas Scalerに登録しておくといいかもしれません。)
もし、ScreenUtilと同じことがしたければ、この辺のコード を移植すればよいのではないでしょうか。
コード量も多くないし、よく使うのであれば。

administrateで名前空間を持つDashboardが選択してもactiveにならないとき

通常、ダッシュボードのナビゲーションは、選択中、文字が太くなる

f:id:rnitta:20200209185515p:plain

が、

ActsAsTaggableOn::TagDashboard みたいに名前空間がくっついている場合、適切に太字にならない問題がある

f:id:rnitta:20200209185631p:plain

module Admin
  class ApplicationController < Administrate::ApplicationController
    protected

    def nav_link_state(resource)
      resource_name.to_s.pluralize == resource.to_s.gsub('/', '__') ? :active : :inactive
    end
  end
end

こうしてしまえばええんじゃ。

f:id:rnitta:20200209185803p:plain

ヨイショ。

administrate/_navigation.html.erb at 1ca811c781a5c225dea6fd4a5d5ba61092952c5b · thoughtbot/administrate · GitHub

administrate/application_controller.rb at a07ea02bc71552e00bcef4d2e471d06df1001e8f · thoughtbot/administrate · GitHub

UnityでInputFieldのパスワードが取得できない

f:id:rnitta:20200206152352p:plain

Unityでログインフォームみたいなものを作る際、

f:id:rnitta:20200206152502p:plain

ContentTypeがPasswordなInputFieldを作り、

f:id:rnitta:20200206152618p:plain

using UnityEngine;
using UnityEngine.UI;

public class SendLoginButton : MonoBehaviour
{
    [SerializeField] Text emailText;
    [SerializeField] Text passwordText;

    public void OnPressed() {
        Debug.Log(emailText.text);
        Debug.Log(passwordText.text);
    }
}

Text#Textで値を呼ぶと、 f:id:rnitta:20200206152829p:plain

パスワードが ********* で取得され、悲しい思いをしました。

=> 解決方法

InputField#text を呼ぶべきでした

f:id:rnitta:20200206153512p:plain

using UnityEngine;
using UnityEngine.UI;

public class SendLoginButton : MonoBehaviour
{
    [SerializeField] InputField emailInput;
    [SerializeField] InputField passwordInput;

    public void OnPressed() {
        Debug.Log(emailInput.text);
        Debug.Log(passwordInput.text);
    }
}

f:id:rnitta:20200206153624p:plain

master.keyを再生成する

雛形プロジェクトをコピーしてきて新しく始める、だとか
master_keyもRAILS_MASTER_KEYも失われてわからなくなってリセットするしか無い、などの状況になったときに
config/master.keyconfig/credentials.yml.enc はどうやったら再生成できるのか調べたのでメモ

A: config/master.keyconfig/credentials.yml.enc を削除して bundle exec rails credentials:edit

f:id:rnitta:20200120124713p:plain

darksky APIのiconとslackのemojiをマッピング

天気予報から今日のステータスアイコンを変更するLambdaを書くときに使ったもの

darksky doc

f:id:rnitta:20191227131707p:plain

def weather_emoji_mapper(weather_icon)
  case weather_icon
  when 'clear-day'
    ':sunny:'
  when 'clear-night'
    ':crescent_moon:'
  when 'rain'
    ':umbrella_with_rain_drops:'
  when 'snow'
    ':snowflake:'
  when 'sleet'
    ':snow_cloud:'
  when 'wind'
    ':wind_blowing_face:'
  when 'fog'
    ':fog:'
  when 'cloudy'
    ':cloud:'
  when 'partly-cloudy-day'
    ':partly_sunny:'
  when 'partly-cloudy-night'
    ':partly_sunny:'
  else
    ':thinking_face:'
  end
end