第65回 Ruby関西 勉強会に参加したよヘ(^o^)ノ
第65回 Ruby関西 勉強会に参加し、発表してきました。
発表内容はRails4.2の新機能について。
4.2がリリースされてから2ヶ月が経ちますが、ActiveJob中心に紹介させてもらいました。
発表中にデモする時があると思います
スライド見ながらタイプするの大変ですよねー( ̄▽ ̄;)
そんな時はtmuxですよ!
- tmuxを起動
- 新しいターミナルから、起動済みtmuxへアクセス
$ tmux attach -t 0
- 普通に操作する
これで発表中のデモも楽ちんですねーヘ(^o^)ノ
Happy Hacking٩( ‘ω’ )و
みなさんの発表内容
Ruby 2.0 以降の変更をふりかえる
RubyでBCCWJを弄ぶ
@pico1aさん
Wakayama.rbボードの紹介
Rubyコミュニティx企業
Medaka.rb活動概要
Gemをコードリーディングしてみよう!
@taiyopさん
Railsの見える化 開発(API編)
@ogomさん
Treasure DataでのRubyの利用
追記
- 2014/02/27 @takamiya_amsさんのスライド追加
Gitのコンフリクト時にmergetoolで確認してマージするヘ(^o^)ノ
Gitでコンフリクトしたときに、GUIやIDEだと差分が確認しやすいみたい。
でも、僕はVimなの...
そこでmergetoolですよ!
実際にやってみよう。
# hello.rb class Hello def say "Hello" end end
コミットして、ブランチを切ります。
$ git init $ git add . $ git commit -m 'first commit' $ git checkout -b add_name
修正してみます。
# hello.rb class Hello def say(name) "Hello #{name}" end end
コミットして、masterブランチへ
$ git add . $ git commit -m 'add name' $ git checkout master
わざとコンフリクトさせてみましょう。
マージする前に、masterブランチのファイルを修正します。
# hello.rb class Hello def say "Hello!" end end
コミットして、マージします。
$ git add . $ git commit -m 'add exclamation mark' $ git merge add_name
コンフリクトしました!
Auto-merging hello.rb CONFLICT (content): Merge conflict in hello.rb Automatic merge failed; fix conflicts and then commit the result.
コマンドを実行します。
$ git mergetool
- 左はマージする前の状態
- 右はマージしたいところ
- 中央は右のマージしたいところが作られる前の状態
- 下はマージして保存するファイル
どうですか?
今のmasterブランチの状態と、マージ前の状態とマージしようとしているファイルの状態が
わかりやすいですよね?
masterブランチには'!'が、add_nameブランチにはnameが追加されています。
ファイルを編集して、保存します。
# hello.rb class Hello def say(name) "Hello #{name}!" end end
コンフリクトしたときのファイルはhello.rb.orig
で保存されています。
必要なければ削除して、コミットしましょう。
$ git commit -m 'merge add_name'
これで、コンフリクトのマージ作業が安全に行えそうですね。
Happy Hacking٩( ‘ω’ )و
d(゚Д゚ )☆スペシャルサンクス☆( ゚Д゚)b
神戸.rb Meetup #12に参加したよーヘ(^o^)ノ
神戸.rb Meetup #12に参加しました。
僕はKonachaについて調べてました。
会社でRailsのJavaScriptをええー感じにテストしたい!ってことなので
# Gemfile group :test, :development do gem 'konacha' gem 'selenium-webdriverd' end
デフォルトのdriverはselenium
です。
実際にテストを書いてみる
# app/assets/javascripts/hello.js.coffee class @Hello @say_hello: (name) -> "Hello #{name}!"
# rspec/javascripts/hello_spec.js.coffee #= require hello describe 'Hello#say_hello', -> it "returns 'Hello murajun1978!'", -> expect(Hello.say_hello('murajun1978')).to.eql("Hello murajun1978!")
テストを実行する
$ bundle exec rake konacha:run . Finished in 0.00 seconds 1 examples, 0 failed, 0 pending
テスト通ったねー
んじゃ、headlessでテストしてみる
# Gemfile gem 'poltergeist' # gem 'selenium-webdriver'
# config/initializers/konacha.rb Konacha.configure do |config| require 'capybara/poltergeist' config.driver = :poltergeist end if defined?(Konacha)
headlessでテストできたねーヘ(^o^)ノ
Happy Hacking٩( ‘ω’ )و
追記
- 2015/02/23
- hello_spec.js.coffeeでrequireしていなかったので追記
- config.driverの指定が間違ってたので修正
神戸.rb Meetup #11 に参加したよヘ(^o^)ノ
Kobe.rbに参加してきたよヘ(^o^)ノ
今日のおやつ!! photo by @spring_aki
おいしかった♪
今日、僕が調べてたのはActiveDecorator + Capybara + RSpecです。
ActiveDecoratorでhelperを良く使いますよねー
例えばこんなの...
def full_name content_tag :td do "#{first_name} #{last_name}" end end
Decoratorが自動生成するRSpecはこちら
describe UserDecorator let(:user) { User.new.extend UserDecorator } subject { user } it { should be_a User } [...] end
毎回extendするのもアレなので、ActiveDecorator::RSpecを使います
# Gemfile gem 'active_decorator-rspec' # spec/decorator/user_decorator_spec.rb describe UserDecorator # FactoryGirlでテストデータ作成 let(:user) { build(:user) } subject { decorate user } it { should be_a User } [...] end
いい感じですねー
キモのfull_nameメソッドをCapybaraでテストしてみましょう
describe UserDecorator [..] it 'has a tr tag and full_name' do expect(subject.name).to have_content(:td, "#{user.first_name} #{user.last_name}") end end
実行すると怒られます。。。
undefined method 'content_tag' for ...
type: :heler
or type: :view
を指定すればhelperメソッドが認識されますが、
こんどはCapybaraにおこられます( ̄▽ ̄;)
have_contentはCapybara::RSpecMatchersで定義されてるのでincludeしてみます
describe UserDecorator include Capybara::RSpecMatchers let(:user) { build(:user) } subject { decorate user } it { should be_a User } it 'has a tr tag' do expect(subject.name).to have_content(:td) end end
これでテストを実行すればパスしますが、毎回includeはアレなのでrails_helperに追記
# spec/rails_helper.rb RSpec.configure do |config| config.include Capybara::RSpecMatchers, type: :decorator end
describe UserDecorator let(:user) { build(:user) } subject { decorate user } it { should be_a User } it 'has a tr tag', type: :decorator do expect(subject.name).to have_content(:td, "#{user.first_name} #{user.last_name}") end end
これでCapybaraを使ってテストできますねー
Happy Hacking٩( ‘ω’ )و
Rails - ActiveDecoratorのコード読んでみたヘ(^o^)ノ
いつもお世話になります。ActiveDecoratorさま。
@izumin5210さんの「ActiveDecorator読んでみたら超勉強になった」を読んで、そういやコードあんま見てなかったので読んでみた
なるほど編
alias_method_chain 既存のメソッドを拡張するときにちょー便利♪
コードよむ編
# lib/active_decorator/monkey/abstract_controller/rendering.rb module AbstractController module Rendering # to_aメソッドのエイリアス↓ def view_assigns_with_decorator # 既存のto_aメソッドをコール hash = view_assigns_without_decorator # メソッドを拡張 hash.values.each do |v| ActiveDecorator::Decorator.instance.decorate v end hash end # :view_assigns => :view_assigns_with_decorator # :view_assigns_without_decorator => :view_assigns alias_method_chain :view_assigns, :decorator end end
view_assignsは、Controllerで取得したインスタンスなんかが格納されたHashを返しますよー
こんな感じ↓
postsはActiveRecord::Relation
です(Post.allしたやつ)
testはインスタンス変数に文字列をいれてみた
このHashをActiveDecorator::Decorator
へ
# lib/active_decorator/decorator.rb module ActiveDecorator class Decorator include Singleton def initialize @@decorators = {} end def decorate(obj) [...] end [...] end end
singletonをMix-inしてるので、ActiveDecorator::Decorator.instance.decorate
で呼び出してますよ
decorateメソッド
if obj.is_a?(Array) # *2でArrayが引数となるのでここ # Arrayの要素(ModelClass)を引数として自身を呼び出してる *3 obj.each do |r| decorate r end elsif defined?(ActiveRecord) && obj.is_a?(ActiveRecord::Relation) && !obj.respond_to?(:to_a_with_decorator) # ActiveRecord::Relationならクラスを再オープンしてメソッド定義してる *1 class << obj def to_a_with_decorator to_a_without_decorator.tap do |arr| # Arrayを引数として自身を呼び出してる *2 ActiveDecorator::Decorator.instance.decorate arr end end alias_method_chain :to_a, :decorator end else # *3で引数がmodelクラスとなるのでここ(ActiveRecord::Relation、Array以外もここ) # decoratorのクラス取得してる d = decorator_for obj.class return obj unless d # PostDecoratorモジュールに属してなければextendしてる obj.extend d unless obj.is_a? d end
decorator_forメソッド
private def decorator_for(model_class) return @@decorators[model_class] if @@decorators.has_key? model_class decorator_name = "#{model_class.name}Decorator" d = decorator_name.constantize unless Class === d d.send :include, ActiveDecorator::Helpers @@decorators[model_class] = d else @@decorators[model_class] = nil end rescue NameError @@decorators[model_class] = nil end
ViewContextをごっそり
# lib/active_decorator/view_context.rb module Filter extend ActiveSupport::Concern included do before_filter do |controller| ActiveDecorator::ViewContext.current = controller.view_context end end end
helperの拡張
# lib/active_decorator/helpers.rb module Helpers def method_missing(method, *args, &block) super #TODO need to make sure who raised the error? rescue NoMethodError, NameError => original_error begin # helperでmethod_missingならActiveDecorator::ViewContextから(なければoriginal_errorの例外発生 ActiveDecorator::ViewContext.current.send method, *args, &block rescue NoMethodError, NameError raise original_error end end end
ViewContextをごっそりとってるから、flashとかもdecoratorで使えるよー
ActiveDecorator::ViewContext.current.flash => #<ActionDispatch::Flash::FlashHash:0x007fda40e27d78 @discard=#<Set: {}>, @flashes={"error"=>"test error"}, @now=nil> ActiveDecorator::ViewContext.current.flash[:error] => "test error" # app/decorators/post_decorator.rb module PostDecorator def error_flash flash[:error] end end
ActiveDecoratorだと読みやすくて勉強にも良いかと思います♪
Happy Hacking٩( ‘ω’ )و
d(゚Д゚ )☆スペシャルサンクス☆( ゚Д゚)b
神戸.rb Meetup #10に行ってきたよヘ(^o^)ノ
今日は神戸.rb Meetup #10に行ってきた。
仕事が押して1時間ほど遅れてしまったけど。。。( ̄▽ ̄;)
みんながそれぞれ興味あることをワイワイ話したり、もくもくしたりと良い感じです。
おやつもあるっ!!!
僕はcocoon(こくーん?)ってgemを使ってみました。
ユーザーストリーにタスクをポンポン追加していくときに使うー
使い方はとても簡単
application.jsに追加
//= require cocoon
- fields_forを使って子モデルを追加したりできるようにする
%h3 Tasks #tasks .field = f.fields_for :tasks do |task| = render 'task_fields', f: task .links = link_to_add_association f, :tasks do = icon('plus-square fa-2x') .actions = f.submit 'Save' # _task_fields.html.haml .nested-fields .field = f.label :name = f.text_field :name = f.label :description = f.text_field :description = link_to_remove_association f do = icon('times fa-2x')
10分くらいでできたサンプルがコレ
そして懇親会♪
神戸ヴァイツェン #koberb pic.twitter.com/zDeAYbm9w9
— カニ (@kanizmb) 2015, 1月 6
ゆりえちゃんのお話もできたしー.。oO(かわいい)
みなさんお疲れ様でしたヘ(^o^)ノ
Rails - ActiveModel::Callbacksでカスタムコールバックヘ(^o^)ノ
あけましておめでとうございます。
年内で仕事が納まらず、1日からコードをごりごり書いております。。。
さて、ActiveRecord::Callbacksはみなさんおなじみ
before_saveとか良く使いますよね?
でも、今回やりたい事はこういうの
# app/models/comment.rb class Comment < ActiveRecord::Base after_publish :send_mail #publishメソッドのCallback def publish [...] end private def send_mail Notifier.comment_published(self).deliver_now end end
ActiveRecordのCallbacksを参考に => active_record/callbacks.rb
# app/models/concerns/comment_callbacks.rb module CommentCallbacks extend ActiveModel::Callbacks extend ActiveSupport::Concern included do define_model_callbacks :publish, only: :after end private def action_after_publish puts '- after publish' end end # app/models/comment.rb class Comment < ActiveRecord::Base include CommentCallbacks after_publish :action_after_publish def publish run_callbacks :publish do puts '> publish!' end end end
$ Comment.new.publish > publish! - after publish
ちゃんとCallbackされましたね
もっと良い実装があれば教えてくだされー
そもそも、この実装が良いのかもわからんし...( ̄▽ ̄;)
Happy Hacking٩( ‘ω’ )و