View customize plugin の v2.6.0 をリリースしました。
中国語のマージリクエストをいただいたので、そちらをマージしてのリリースとなります。
View customize plugin の v2.6.0 をリリースしました。
中国語のマージリクエストをいただいたので、そちらをマージしてのリリースとなります。
java.sql.Time
には、下記のようなLocalTime
との間で変換を行うメソッドがあります。
ただ、これらメソッドは秒までしか対象にしておらず、ミリ秒が破棄されています。
/** * Obtains an instance of {@code Time} from a {@link LocalTime} object * with the same hour, minute and second time value as the given * {@code LocalTime}. * * @param time a {@code LocalTime} to convert * @return a {@code Time} object * @exception NullPointerException if {@code time} is null * @since 1.8 */ @SuppressWarnings("deprecation") public static Time valueOf(LocalTime time) { return new Time(time.getHour(), time.getMinute(), time.getSecond()); } /** * Converts this {@code Time} object to a {@code LocalTime}. * <p> * The conversion creates a {@code LocalTime} that represents the same * hour, minute, and second time value as this {@code Time}. * * @return a {@code LocalTime} object representing the same time value * @since 1.8 */ @SuppressWarnings("deprecation") public LocalTime toLocalTime() { return LocalTime.of(getHours(), getMinutes(), getSeconds()); }
面倒ではありますが、LocalDateTimeなどを経由させて変換することによって、ミリ秒を維持したまま変換できます。
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss.SSS"); DateTimeFormatter localTimeFormat = DateTimeFormatter.ofPattern("HH:mm:ss.SSS"); LocalTime baseLocalTime = LocalTime.now(); // baseLocalTime: 01:41:44.369 System.out.printf( "baseLocalTime: %s\n", baseLocalTime.format(localTimeFormat)); { // NGなパターン Time time = Time.valueOf(baseLocalTime); LocalTime localTime = time.toLocalTime(); // time: 01:41:44.000 localTime: 01:41:44.000 equals: false System.out.printf( "time: %s localTime: %s equals: %s\n", timeFormat.format(time), localTime.format(localTimeFormat), baseLocalTime.equals(localTime)); } { // OKなパターン Time time = new Time( baseLocalTime.atDate(LocalDate.ofEpochDay(0)) // LocalDateTimeに変換 .atZone(ZoneId.systemDefault()) // ZonedDateTimeに変換 .toInstant().toEpochMilli()); // Epochミリ秒へ LocalTime localTime = LocalDateTime.ofInstant( // Epochミリ秒からLocalDateTimeへ Instant.ofEpochMilli(time.getTime()), ZoneId.systemDefault()).toLocalTime(); // time: 01:41:44.369 localTime: 01:41:44.369 equals: true System.out.printf( "time: %s localTime: %s equals: %s\n", timeFormat.format(time), localTime.format(localTimeFormat), baseLocalTime.equals(localTime)); }
上記の問い合わせに対応したサンプルコードを書いてみました。
親のカスタムフィールド(キーバリュー形式のリスト)が選択されたら、子のカスタムフィールドを有効化するコードです。
Redmineのデフォルトのスタイルだと、input:disabled
のbackground-color
が設定されておらず、disabledになったことがわかりずらかったので、明示的にbackground-color
を変えるようにしています。(CSSにしても良かったけど、一つのサンプルコードにまとめたかったので、、)
.*
Bottom of issue form
$(function() { const parentField = $('#issue_custom_field_values_1'); const childFields = [ $('#issue_custom_field_values_2'), $('#issue_custom_field_values_3'), $('#issue_custom_field_values_4') ]; const changeEnable = function() { if (parentField.val() != '') { childFields.forEach(function(child) { child.prop('disabled', false); child.css('background-color', ''); }); } else { childFields.forEach(function(child) { child.prop('disabled', true); child.css('background-color', '#ebebe4'); }); } } parentField.change(changeEnable); changeEnable(); })
先日Twitter上で外部キーが話題にあがっていました。自分も大昔は外部キーを重要視していませんでしたが、1x年以上たった今では、様々な制約等を使って、RDBMS上でデータの整合性を保つべきと考えています。
データの不整合を、プログラム側で検知するのは難しいです。プログラム側ではデータがこうあるべきといった定義ができないためです。
そこでデータの格納先であるRDBMS側でデータの整合性を保証することが重要です。
プログラムのバグなどで不整合なデータが格納されてしまうと、不整合なデータを格納しようとしたトランザクションだけでなく、システム全体に影響を及ぼすことになりかねません。制約等ではじければ、エラーとなるのは不整合なデータを格納しようとしたトランザクションだけで、システム全体に影響を及ぼすということを防げます。
また、制約として定義することによって、「アプリケーションの仕様的に、こういったデータが格納されることはない」っていうのではなく、スキーマとしてデータの仕様を可視化することができます。
RDBMSはデータの整合性を保つために、様々な制約が用意されています。
下記はPostgreSQLのマニュアルで各制約の説明をしたページです。他のRDBMSでも同じようなものだと思います。(MySQLでも最近検査(CHECK)制約が追加されましたね!)
検査制約では、関数呼び出しもできるので、複雑なチェック処理をFUNCTIONとして定義しておいて、それを呼びだしてチェックするといったこともできます。
また、一意制約でも関数を使えるので、大文字小文字関係なく一意であるといったような制約も付与できます。
※各制約がどういったものかは後で追記するかも
当たり前のことかもしれませんが、データの型を正しく利用するといったことも重要です。たとえば数値を文字列型(VARCHARやTEXT)に格納してしまうと、データとしての整合性を維持する手段を手放してしまっていることになります。
また、数種類の文字列しか入らないようなものは、ENUM(列挙型)を使うことによって、何がはいるのかを限定することができます。種別を数値で入れているようなところも、ENUMにした方がデータとしてわかりやすくなるかもしれません。
ただし、取りえる値が変わるようなものに対して、このような制約を付けるのはメンテナンス性を落とす可能性もあるのでご注意ください。(SQLアンチパターンでも触れられているところで、参照テーブルを用意してそちらとの外部キーで制限した方がよい)
INSERTやUPDATE、DELETE時のパフォーマンスが落ちるから、、といった理由で外部キー制約や検査制約を避けることがあるというのを、ネット上で見かけたことがあります。
実際に制約がパフォーマンス的に問題を起こしているということがわかったならば、制約を外すなり、違った形での制約に変えるなりすればよいと思いますが、最初から避けるのはとてももったいないかな、、と思っています。データの整合性がRDBMS上で保証されているというのは、プログラムを書くうえで大きな安心を得られますし、生産性をあげるものだとも思っています。
上記の問い合わせの中で、カスタムフィールドを3カラム表示したいといったのがあったので、サンプルコードを書いてみました。
.*
Bottom of issue form
$(function() { const field1 = $('#issue_custom_field_values_1'); const field2 = $('#issue_custom_field_values_2'); const field3 = $('#issue_custom_field_values_3'); // Change layout const content = $('<div class="splitcontent">') .append($('<div class="splitcontentleft">').append(field1.parent())) .append($('<div class="splitcontentleft">').append(field2.parent())) .append($('<div class="splitcontentright">').append(field3.parent())); $('#attributes').append(content); })
カスタムフィールドが大量にあって、少しでも詰めて表示したい、、って時には有用かもしれません。
この記事はRedmine Advent Calendar 2019 19日目の記事です。
Redmine Users (Japanese)のメーリングリストで流れていた件で、既にJavaScriptで解決する方法が他の方から出ていましたが、CSSでもできるのでCSSで書いてみました。
.*
Head of all pages
下記はa
という識別子のプロジェクトに対して無効とする書き方です。
.project-a #issue-form #attachments_form, .project-a #issue-form .attachments_form { display: none; }
下記のような感じで非表示になります。
チケットの編集時はちょっと微妙でタイトルまでは消しませんでした。ちょうど良いidやclassが振られていなくて、タイトル含めて消そうとすると #issue-form .filedroplistner fieldset:last-child
で指定するくらいしかないのですが、必ず最後になるのか確信がもてなかったのでやめました。
JavaScriptの方がいろいろなことができるので、View customizeのサンプルもJavaScriptを使ってものが多くなりますが、CSSの方がシンプルに書けることも多いので、シンプルなデザイン的なもの(今回の非表示のように)は、CSSで書くことが多いです。
プロジェクトの識別子のように、いろんな情報がHTML上に付与されているので、一度DOMインスペクタなどで眺めてみると良いと思います。
この1か月くらい、家では諭吉佳作/menさんの曲を聴きまくっている。それくらいハマっている。
最初に諭吉佳作/menさんを知ったのは、9月にNHK Eテレで放送された「前山田×体育のワンルーム☆ミュージック」だった。インタビューで、「打ち込みだったら腕が3本なければ叩けないような曲も作れる」(もっと違うニュアンスだったかも)ってとこが印象に残っている。
この時点では、名前は知っている(名前の印象はとても強い)くらいでしかない状態で、特に曲を聴いてみようとはならなかった。この時本人が歌っている曲が流れていたら、きっとこの時点ですぐにハマっていたと思う。
このとき番組で流れていたのは楽曲提供していたでんぱ組.incのMVだった。
そのあと、SpotifyでWeekly Buzzか何か聞いているときに、崎山蒼志くんの「むげん・ (with 諭吉佳作/men)」が流れて、この声って諭吉佳作/menさん!?ってなった。
Spotifyにはほとんど曲がなかったので、YouTube、SoundCloudで曲を聴いた。すごくいい。
曲自体も良いのだけど、そこに声が重なってさらに魅力的なものになっている。この曲とこの声が組み合わさることによる相乗効果というかなんというか。
どれもオリジナリティあふれる楽曲で、ビリー・アイリッシュを初めて聞いた時の感覚に似てる。(ビリー・アイリッシュの曲を初めて聞いた時も、とてもインパクト受けた)
一番のお気に入りは「洋装の語る今日は」で、リズミカルに流れる曲の上でさらに流れるような声、、すごくいい。
ちなみに、うちの娘たちは「の ぞ き」がお気に入りで、よく口ずさむようになった。
移動中などにも聞きたいので、Spotifyで配信(課金してるので、ネット接続なくても聴ける)するか、アルバム出して欲しいです。もしくはダウンロード販売でも。
同じように思っている人は既にいっぱいいそうなので、すぐ近い将来そうなるんだろうな。とても楽しみ。