jQueryでアコーディオンパネルを作る
最近javascriptを使えないと世の中的にやばいんじゃないかと思いjQueryを勉強し始めました…。
勉強してる中でアコーディオンパネルを作ったわけなんですが、想像以上に簡単に実装できちゃう感じを知り若干感動したのでブログ化です。
(これで感動しているあたり素人感丸出しなのは内緒。)
今更こんなん記事にします?っていう指摘は言わないであげてください。笑
アコーディオンパネルってなんや
アコーディオンパネルはクリックするとクリックした項目の下に文字なんかがスライドで出てきて、もう一回クリックするとスライドしてもとに戻るやつです。
説明下手すぎてイメージつかないですね。
つまりこんな感じのやつです。
初期表示
でこれの一番上の項目をクリックすると
こんな感じでクリックするとヌルッと出てくるやつです。
もう一回同じ項目をクリックすると初期表示の状態に戻ります
とりあえず作ってみよう
ということでまずはHTMLとCSSを作ります。
HTML
<ul id="accordion mdl-list"> <li class="accordion-item mdl-list__item"> <h3 class="question">職業はなんですか?</h3> <span>+</span> <div class="answer"> <p>システムエンジニアです。いわゆるSEです。</p> </div> </li> <li class="accordion-item"> <h3 class="question mdl-list__item">なんのスポーツが好きですか?</h3> <span>+</span> <div class="answer"> <p>野球</p> </div> </li> <li class="accordion-item mdl-list__item"> <h3 class="question">携帯は何使ってますか?</h3> <span>+</span> <div class="answer"> <p>iPhone</p> </div> </li> </ul>
初期に表示されている箇所がh3要素、出たり隠れたりする箇所が<div class="answer">~</div>
の部分になります。
CSS
ul { list-style: none; } .accordion-item { position: relative; width: 400px; border-bottom:1px solid #ccc; cursor: pointer; margin-top: 5px; } .accordion-item:hover { background-color: #E6E6E6; } .question { font-size: 18px; margin: 0; padding: 0; } .accordion-item span { position: absolute; top: 5px; right: 5px; color: #B3B3B3; font-size: 20px; } .answer { display: none; font-size: 12px; }
初期表示の状態では出たり隠れたりする部分をdisplay: none;
で画面に表示されないようにしておきます。
javascriptを書くッッ
さてアコーディオンパネルを実現するためのjavascriptを書きます。
とはいってもjQueryを使うとすごくさっくりした記述で処理が書けちゃいます!
$(function() { $('.accordion-item').click(function(){ //出隠れする部分を変数に格納しておく var $answer = $(this).children('.answer'); //hasClassメソッドで出隠れする部分にopenが存在するか確認 if ($answer.hasClass('open')) { //出隠れ部分が出ている場合の処理 //<div class="answer open">からopenを消す $answer.removeClass('open'); //出ている部分をスライドアップして隠す $answer.slideUp(); //横っちょにある開閉ボタンを+に変える $(this).children('span').text('+'); } else { //出隠れ部分が隠れている場合の処理 //<div class="answer">にopenを追加する $answer.addClass('open'); //出す部分をスライドダウンして表示させる $answer.slideDown(); //横っちょにある開閉ボタンを-に変える $(this).children('span').text('-'); } }); });
<div class="answer">
にopenを追加することで開いたり、隠したりする感じ。
openを追加することでCSSに記載しているdisplay: none;
が無効になったり、有効になったりするイメージかしら。
とはいえたった10行前後で良く見るあのアコーディオンパネルさんを実現できるのはちょっと感動。
Ruby on Railsを極めつつ、javascriptも極めていきたいっすなあ。
とはRailsさんはcoffeescriptだからまた勉強が必要やが…。
そのうちcoffeescript備忘録つくろ
Railsで関連モデルを同時に更新したい(has_oneで関連させていたモデルをbuild_associationで安直に生成しようとしたら痛い目をみた話)
Railsで関連モデルを同時に更新するようなコードを書こうとして、思いの外ハマって抜けられなくなったので備忘録。
関連モデルを同時に更新したい状況
例えばメールアドレスやパスワードのような認証情報と、生年月日や趣味のようなプロフィール情報を分けて管理したい場合など結構ありがちだと思います。 以下のような関連を持つモデルのようなイメージ。
とりあえず書いてみる
ひとまず自分の思うがままにコードを書いていく。
まずモデルから。
app/models/user.rb
class User < ActiveRecord::Base has_one :profile, dependent: :destroy accepts_nested_attributes_for :profile end
app/models/profile.rb
class Profile < ActiveRecord::Base belongs_to :user end
親モデルのUserにaccepts_nested_attributes_for
を設定することで親モデルから子モデルを作成したり、保存したりできるようにする。
次にコントローラ。
app/controllers/users_controller.rb
class UsersController < ApplicationController before_action :set_user, only: [:show, :edit, :update, :destroy] def index @users = User.all end def show end def new @user = User.new end def edit @user.build_profile end def create @user = User.new(user_params) @user.save redirect_to :users end def update @user.update(user_params) redirect_to :users end def destroy @user.destroy redirect_to :users end private def set_user @user = User.find(params[:id]) end def user_params params.require(:user).permit(:email, :password, profile_attributes: [:birthday, :hobby]) end end
viewでfields_for
を使うのでprofile_attributes
をストロングパラメータに記入しておく。
(fields_for
は[引数に与えた名前]_attributes
というname属性になるためらしい)
仕様としてプロフィール情報を入れるのはユーザ情報編集時のみとするため、登録しているUserモデルからProfileモデルを生成できるようにedit
に@user.build_profile
と何気なく記入。
親から子を生成するときはとりあえずbuildっしょとかいう素人考えでbuild_profileを記入したが 、後にどツボへの道へと誘うことになるとはこの段階では知る由もなかった…。
とりあえず次にビュー。
app/views/_form.html.erb
<%= form_for(@user) do |f| %> <% if @user.errors.any? %> <div id="error_explanation"> <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2> <ul> <% @user.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> </div> <% end %> <div class="field"> <%= f.label :email %><br> <%= f.text_field :email %> </div> <div class="field"> <%= f.label :password %><br> <%= f.password_field :password %> </div> <% unless current_page?(new_user_path) %> <%= f.fields_for :profile, @user.profile do |pf| %> <div class="field"> <%= pf.label :birthday %><br> <%= pf.date_field :birthday %> </div> <div class="field"> <%= pf.label :hobby %><br> <%= pf.text_field :hobby %> </div> <% end %> <% end %> <div class="actions"> <%= f.submit %> </div> <% end %>
プロフィール情報はnewのタイミングでは表示させないようにcurrent_page?
を設定。
fields_for
のタグを<%= %>
ではなく<% %>
で記入してプロフィール情報入力欄出ない問題にも軽くハマっているのは内緒の話。
これでとりあえず一通り完成!
てことで動作確認
ユーザを登録
次にプロフィール情報を入力するために編集
いい感じにプロフィール情報を入力できるようになっている。
とりあえずプロフィール情報を入力。
登録できたか確認
いい感じに登録できている。
しかし、問題が起きる…
登録までできて、「いやー、ひと仕事終わったよ」と清々しい気分でいましたが、再び編集画面を表示した際に違和感を覚える。
あれ…?プロフィール情報が表示されてなくね…?
いやいや、まさかそんなはずは…と思い、再びshowしてみるとProfileモデルなんて存在してねーけど…と怒られる。
DBも確認してみたが、profilesテーブルがまっさらになっている…
>> Profile.all Profile Load (0.5ms) SELECT "profiles".* FROM "profiles" => #<ActiveRecord::Relation []>
さっきまで存在していたプロフィール情報がどこか遠い国に旅立ってしまっている…
登録し直したり、デバッグしてみたりで原因を探ること小一時間。
問題点があらわになる。
@user.build_profile
を実行した後にレコードが消えている…!!!!!
サーバログを見てみると
Started GET "/users/8/edit" for ::1 at 2016-02-07 12:12:38 +0900 Processing by UsersController#edit as HTML Parameters: {"id"=>"8"} User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 8]] Profile Load (0.2ms) SELECT "profiles".* FROM "profiles" WHERE "profiles"."user_id" = $1 LIMIT 1 [["user_id", 8]] (0.1ms) BEGIN SQL (0.2ms) DELETE FROM "profiles" WHERE "profiles"."id" = $1 [["id", 7]] (2.0ms) COMMIT Rendered users/_form.html.erb (3.0ms) Rendered users/edit.html.erb within layouts/application (4.2ms) Completed 200 OK in 38ms (Views: 20.1ms | ActiveRecord: 2.7ms)
なんかDELETEが走っちゃってますけど!!!!
どうもbuild_profile
でProfileモデルを生成の際は一旦存在するレコードを消してから生成みたいなことが起きているっぽい。
ということでbuild_profile
を使わないように修正。
def edit @user.profile = Profile.new if @user.profile.blank? end
てな感じで無事プロフィール情報を登録してから編集画面にいっても情報が消えなくなりました。
とりあえず関連モデルを生成するならbuildじゃね?という安易な考えを悔い改めようと思いましたまる
vagrant環境でrake db:migrateが失敗する
vagrant環境でRailsでrake db:migrateを実行する際にエラーが出て時間を食ってしまったので備忘録
使用しているDBMSはpostgresql
$ rake db:migrate rake aborted! ActiveRecord::NoDatabaseError: FATAL: role "vagrant" does not exist PG::ConnectionBad: FATAL: role "vagrant" does not exist
どうやらvagrantなんてロールはいないよとのこと。。。
なのでvagrantロールを作成してやることに。
$ sudo su - postgres $ psql $ create role vagrant with createdb login $ \du Role name | Attributes | Member of -----------+-------------+----------- postgres | Superuser | {} : Create role Create DB vagrant | Create DB | {}
とりあえずDB作れる権限だけ与えて、vagrantロールを作成 postgresqlからexitして再びmigrate
$ rake db:migrate rake aborted!</span> ActiveRecord::NoDatabaseError: FATAL: database "app_development" does not exist PG::ConnectionBad: FATAL: database "app_development" does not exist
今度はapp_developmentなんてDBは存在しないよとのこと。。。
今度はDBを作成してやることに。
$ sudo su - postgres $ psql $ create database app_development CREATE DATABASE
これでDBも作成できたので、またexitしてmigrate
$ rake db:migrate == 20151103022733 CreateProjects: migrating =================================== -- create_table(:projects) -> 0.0277s == 20151103022733 CreateProjects: migrated (0.0278s) ==========================
無事migrateができた。
なんかすごい初歩的なことに時間を取られた。。。
前はこんな設定せずにサクッとrailsが使えた記憶があったせいか、なおさら時間がかかった。。。
今度はherokuなんかにあげるときに問題が起きそうな予感。。。
とりあえずmigrateできたのでガシガシアプリ作りに励みます。
ブログはじめました
はじめまして。KMRです。
社会人2年目のSIerです。 現在、Web系で働くことを夢見て、絶賛Ruby on Railsを勉強中です。
ブログを始めるに至った経緯としては
- 勉強していることの備忘録を作りたい
- アウトプットすることでより自分の理解を深めたい
- 情報発信力が求められる世の中なので、その訓練に
- 情報を発信していくことで自分の中の何かを変えたい
的な経緯があります。
今後、記事を書いていく内容としては
- 勉強の備忘録
- 本やコラムを見ての感想
- 個人的な思いとか、日常風景とか。。。
みたいな感じで書いていきたいと思います。
まずは情報を発信していく訓練をしていきたい所存です。 これからよろしくお願いします!