classキーワードとclass_evalメソッド
Module.class_evalメソッドってどういうときに使うんだっけ、どうしてclassキーワードを使わないんだろと、ふと気になったので簡単にまとめておく。
classキーワード
- 定数(クラス名)を必要とする
- 現在の束縛を捨てて、新しいスコープをオープン
- classはスコープゲートとして振る舞う
class_eval (module_eval)
- クラスを参照する変数なら何でも使える、クラス名がわからなくてもよい
- フラットスコープを持つ
- class_evalブロックの外にあるスコープにある変数も参照することができる
そもそも、class_evalメソッドはレシーバをコンテキストとして文字列やブロックを評価するメソッド。
Fixnum.class_eval{ def number;self;end} 7.number #=> 7
ブロック同様、文字列も評価する。
Fixnum.class_eval "def number ; self ;end" 5.number #=> 5
evalメソッド同様、privateメソッドの呼び出しも可能なので、使用する際には注意が必要。
Rubyリファレンスを見てみると、次のような記述がある。
class_evalメソッドは、ブロックをクラス定義やモジュール定義の中のコードであるように実行します。ブロックの戻り値がメソッドの戻り値になります。
module_evalメソッドはclass_evalの別名です。Classオブジェクトに対してmodule_evalを呼び出せますし、Moduleオブジェクトに対してclass_evalを呼び出せます。
ブロック内でのselfはClassオブジェクトやModuleオブジェクトを指します。ブロックの外側のローカル変数はブロック内でも使えます。
class_eval、module_evalを使うと、クラスやモジュールの外側でインスタンスメソッドを定義したり、Moduleクラスのprivateメソッドを呼び出したりできます。
なるほど。
ActiveRecord::Base.find
よくお世話になっているくせにRailsのfindメソッドのコードを初めて読んだので、メモ。
activerecord-2.3.2/lib/active_record/base.rb
def find(*args) options = args.extract_options! validates_find_options(options) set_readonly_options!(options) case args.first when :first then find_initial(options) when :last then find_last(options) when :all then find_every(options) else find_form_ids(args, options) end end
ちなみに、find_initialメソッドとfind_everyメソッドはこんな感じ。
結局はfind_everyメソッドに集約されてる。
eager_loadingの仕組みが垣間見えて面白い。
activerecord-2.3.2/lib/active_record/base.rb
def find_initial(options) options.update(:limit => 1) find_every(options).first end def find_every(options) include_associations = merge_includes(scope(:find, :include), options[:include]) if include_associations.any? && references_eager_loaded_tables?(options) records = find_with_associations(options) else records = find_by_sql(construct_finder_sql(options)) if include_associations.any? preload_associations(records, include_associations) end end records.each { |record| record.readonly! } if options[:readonly] records end
extract_options!
お馴染みextract_options!メソッドですが、
正確なコードを忘れてしまっていたので備忘録としてメモ。
module Arrayで定義されているのが個人的に面白いと感じたり。
Rails : 2.3.2
module ActiveSupport module CoreExtensions module Array module ExtractOptions def extract_options! last.is_a?(::Hash) ? pop : {} end end end end end
モンキーパッチの防止(Rakeの場合)
Rubyは動的言語であり、メタプログラミングを駆使すれば魔術のようなこともできる。
一方で、一歩間違えればコードの複雑性が上がり、可読性が下がってしまう危険性があるどころか、思わぬ挙動を引き起こしてしまうこともある。
テストを必要十分に書くということでそのようなミスを防ぐことはできるが、
コードを実際に書くときにも気をつけられることはないか。
ということでビルドシステムであるRakeのコードを簡単に見てみる。
gems/rake-0.8.7/lib/rake.rb
class Module def rake_extension(method) if method_defined?(method) $stderr.puts "WARNING: Possible conflict with Rake extension: \#{self}##{method} already exists" else yield end end end
Rakeで上記のように定義することにより、
新規にメソッドを定義する際、例えば以下のように書いて安全確認をすることができる。
class String rake_extension('ext') do def ext(newext = '') # do something end end end
このようにすることで、Rubyのコアライブラリが将来String#extを定義するようになったら、例外を吐いて警告もらえる。
ActiveRecord::AttributeMethods
明けましておめでとうございます。
本年もよろしくお願いいたします。
新年早々、ActiveRecordのコードを読んでいて書き方が勉強になったので、
今後の参考にメモしておきます。
ちなみに、もともとはinstance_method_already_implemented?メソッドを見たかっただけで、
これはActiveRecordで動的メソッドを定義する前に、同じメソッドが存在しないかどうかを確認するために利用されています。
動的メソッドアクセサを生成する前にこのメソッドが呼び出されている様子。
rails / activerecord / lib / active_record / attribute_methods.rb
require 'active_support/core_ext/enumerable' require 'active_support/deprecation' module ActiveRecord # = Active Record Attribute Methods module AttributeMethods #:nodoc: extend ActiveSupport::Concern include ActiveModel::AttributeMethods included do include Read include Write include BeforeTypeCast include Query include PrimaryKey include TimeZoneConversion include Dirty include Serialization include DeprecatedUnderscoreRead # Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example, # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). # (Alias for the protected read_attribute method). def [](attr_name) read_attribute(attr_name) end # Updates the attribute identified by <tt>attr_name</tt> with the specified +value+. # (Alias for the protected write_attribute method). def []=(attr_name, value) write_attribute(attr_name, value) end end module ClassMethods # Generates all the attribute related methods for columns in the database # accessors, mutators and query methods. def define_attribute_methods unless defined?(@attribute_methods_mutex) msg = "It looks like something (probably a gem/plugin) is overriding the " \ "ActiveRecord::Base.inherited method. It is important that this hook executes so " \ "that your models are set up correctly. A workaround has been added to stop this " \ "causing an error in 3.2, but future versions will simply not work if the hook is " \ "overridden. If you are using Kaminari, please upgrade as it is known to have had " \ "this problem.\n\n" msg << "The following may help track down the problem:" meth = method(:inherited) if meth.respond_to?(:source_location) msg << " #{meth.source_location.inspect}" else msg << " #{meth.inspect}" end msg << "\n\n" ActiveSupport::Deprecation.warn(msg) @attribute_methods_mutex = Mutex.new end # Use a mutex; we don't want two thread simaltaneously trying to define # attribute methods. @attribute_methods_mutex.synchronize do return if attribute_methods_generated? superclass.define_attribute_methods unless self == base_class super(column_names) column_names.each { |name| define_external_attribute_method(name) } @attribute_methods_generated = true end end def attribute_methods_generated? @attribute_methods_generated ||= false end # We will define the methods as instance methods, but will call them as singleton # methods. This allows us to use method_defined? to check if the method exists, # which is fast and won't give any false positives from the ancestors (because # there are no ancestors). def generated_external_attribute_methods @generated_external_attribute_methods ||= Module.new { extend self } end def undefine_attribute_methods super @attribute_methods_generated = false end def instance_method_already_implemented?(method_name) if dangerous_attribute_method?(method_name) raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord" end if superclass == Base super else # If B < A and A defines its own attribute method, then we don't want to overwrite that. defined = method_defined_within?(method_name, superclass, superclass.generated_attribute_methods) defined && !ActiveRecord::Base.method_defined?(method_name) || super end end # A method name is 'dangerous' if it is already defined by Active Record, but # not by any ancestors. (So 'puts' is not dangerous but 'save' is.) def dangerous_attribute_method?(name) method_defined_within?(name, Base) end def method_defined_within?(name, klass, sup = klass.superclass) if klass.method_defined?(name) || klass.private_method_defined?(name) if sup.method_defined?(name) || sup.private_method_defined?(name) klass.instance_method(name).owner != sup.instance_method(name).owner else true end else false end end ...
method_missing
メソッド呼び出しに失敗した場合、method_missingメソッドが呼び出される。
ここまでは既知ですが、
このmethod_missingメソッド、通常のメソッドと同様に、
当該クラスから探し、見つからなければ継承階層をスーパークラスへと登っていくとのこと。
method_missingメソッドが見つかるか、Objectクラスにたどり着くまでこれをくり返す。
Objectクラスのmethod_missingは単純にNoMethodError例外を発生させるだけ。
そんなわけで、試しにmethod_missingメソッドをオーバーライドしてみた。
gist使いたかっただけです。すみません。。
私の取り扱い説明書
少し前にドラッカーの『プロフェッショナル』の条件を再読してみて、
改めて「何かをなし遂げるのは、強みによってである」ということを学んだ。
そんなわけで、
自分の強みについて改めて振り返って今後の指針にしたかったので遅くなったけど、
『さあ、才能に目覚めよう』を読んでまとめてみる。
本書には、強みの活かし方について書かれた章もあり、
後半ではそこで書かれていることについても言及します。
言わば私の取り扱い説明書みたいなものなので、
あいつ扱いにくいなと思ってる方はぜひご参照くださいm(_ _)m
『さあ、才能に目覚めよう』によれば、私の強みは
- 慎重さ
- 学習欲
- 収集心
- 調和性
- 個別化
とのこと。
それぞれについてもう少し深掘りしていきます。
慎重さ
本書に書いてある慎重さについてまとめると以下のようになる。
自分と合っているなあと思うところには◆、もっと気をつけなければいけないと思うところには下線を引いておきます。
- 用心深く、決して油断しない◆
- 自分のことをあまり話さない◆
- 世の中が予測できない場所であることを知っている
- すべてが秩序正しいように見えるが、表面化には数多くの危険が待ちかまえていることを感じ取っている
- これらの危険を否定するよりは、一つひとつを表面に引き出す◆
- 危険は1つずつ特定され、評価され、最終的に減っていく◆
- 言うなれば、毎日の生活を注意深く送る、かなりまじめな人◆
- たとえば、何かがうまくいかない場合に備えて、あらかじめ計画を立てることを好む◆
- 友人を慎重に選び、会話が個人的な話題になると、自分のことについては話をせず、自分自身で考えることを好む◆
- 誤解されないように、過度に褒めたり認めたりしないように気をつける◆
- 人になかなか打ち解けないという理由で、自分のことをを嫌う人がいても気にしない◆
- 自分にとって、人生は人気コンテストでない◆
- 危険を明確にし、その危険が及ぼす影響を推し量り、それから慎重に一歩ずつ踏み出す
- 細心の注意を払って進む
ディック・H(映画プロデューサー)
私の仕事は不確定要素を減らすことだ。不確定要素が少なければ少ないほどリスクも減る。
ディレクターと話し合いをするときには、いつもまず小さな問題をすぐ片づける。
それがすむと、ちょっとほっとする。
それができると、あとは重要なことに集中でき、話し合いの主導権を握ることができるからだ」
学習欲
- 学ぶことが大好き◆
- 最も関心を持つテーマは、自身のほかの資質や経験によって決まりますが、それがなんであれ、いつも学ぶ「プロセス」に心を惹かれる◆
- 内容や結果よりもプロセスこそが、自分にとっては刺激的◆
- 何も知らない状態から能力を備えた状態に、着実で計画的なプロセスを経て移行することで活気づけられる◆
- 最初にいくつかの事実に接することでぞくぞくし、早い段階で学んだことを復誦し練習する努力をし、スキルを習得するにつれ自信が強まるーーこれがあなたの心を惹きつける学習プロセス◆
- 意欲の高まりは、あなたに社会人学習ーー外国語、ヨガ、大学院などーーへの参加を促すようになる◆
- それは、短期プロジェクトへの取り組みを依頼されて、短期間でたくさんの新しいことを学ぶことが求められ、そしてすぐにまた次の新しいプロジェクトに取り組んでいく必要のあるような、活気にあふれた職場環境の中で力を発揮する◆
- この「学習欲」という資質は、必ずしもあなたがその分野の専門家になろうとしているとか、専門的あるいは学術的な資格に伴う尊敬の念を求めていることを意味するわけではない
- 学習の成果は、「学習のプロセス」ほど重要ではない
アニー・M(編集長)
何かを学んでいないと落ち着かないタイプね、私は。
たとえば去年、仕事には満足してたけど、なんとなく学び足りない気がしたんで、タップダンスを習いはじめたの。
これって変?
どう考えたってすごくうまくはならない。それはわかってる。
でも、タップの基本を一生懸命覚え、毎週少しずつうまくなって、初心者クラスから中級クラスに上がれるのがうれしいの。そこがポイントね。
収集心
- 知りたがり屋◆
- ものを収集する人◆
- あなたが収集するのは情報ーーことば、事実、書籍、引用文ーーかもしれない◆
- あるいは形あるもの、たとえば、切手、野球カード、ぬいぐるみ、包装紙などかもしれない◆
- 集めるものが何であれ、あなたはそれに興味を惹かれるから集める◆
- あなたのような考え方の人は、いろいろなものに好奇心を覚える◆
- 世界はかぎりなく変化に富んでいて複雑なので、とても刺激的に感じる
- もしあなたが読書家だとしたら、それは必ずしも自分の理論に磨きをかけるためではなく、むしろ自分のの蓄積された情報を充実させるため
- もし旅行が好きだとしたら、それは初めて訪れる場所それぞれが、独特な文明の産物や事柄を見せてくれるから
- これらを手に入れた後、保管しておきたがる◆
- あらゆる利用の可能性を考えているため、ものを捨てることに不安を感じる◆
- それゆえ、ものや情報を手に入れ、集め、整理して保管しつづける◆
- それを面白いと感じる◆
- それがあなたの心を常に活き活きとさせる◆
- そしておそらくある日、その中に役に立つものが出てくることでしょう
調和性
- 同意点を求める◆
- 衝突や摩擦から得るものはないという考えを持っているため、そのような争いを最小限にしようとする◆
- 周囲の人々が異なる意見を持っていることがわかると、あなたはその中の共通する部分を見出そうとする◆
- 彼らを対立から遠ざけて調和に向かわせようとする◆
- 事実、調和はあなたの行動を左右する価値観の一つ◆
- 人々が自分の意見を他人に押しつけるために無駄にしている時間の多さは、信じがたいほど◆
- ほかの人が自分の目標や、主張や、強く抱いている意見を声高に話しているとき、あなたは沈黙を守る◆
- ほかの人がある方向に動きだすと、あなたは調和という名のもとに(彼らの基本的価値観があなたの価値観と衝突しないかぎり)、喜んで彼らに合わせてあなた自身の目標を修正する◆
- ほかの人たちが自分たちのお気に入りの理論や考えについて議論を始めると、論争を避ける方向に持っていき、全員が賛同できる、実用的で地に足の着いた事柄について話すことのほうを取る◆
- あなたの見方では、私たちは全員同じ船に乗り合わせていて、この船をこれから行こうとしているところに到着させる必要がある◆
- 単に自分が船を揺すれることを示すために、わざわざ船を揺する必要などない◆
個別化
- あなたは個別化という資質により、一人ひとりが持つユニークな個性に興味を惹かれる
- あなたは一人ひとりの何が特別でどこが個性的なのかを覆い隠したくないので、人を一般化したり、あるいは類型化することに我慢できない◆
- むしろ、個人個人のちがいに注目する
- 本能的にそれぞれの人の性格、動機、考え方、関係の築き方を観察している
- それぞれの人生における、その人にしかない物語を理解する
- この資質によって、あなたは、友達にぴったりの誕生日プレゼントを選んだり、ある人は人前で誉められることを好み、別の人はそれを嫌うことがわかったり、一から十まで説明してほしい人と、一を示せば十を知る人とに合わせて教え方を調整できたりする◆
- ほかの人の強みをとても鋭く観察する人なので、一人ひとりの最もよいところを引き出すことができる
- この個別化という資質は、生産性の高いチームをつくることにも役立つ
- 完璧なチームをつくるにあたり、チームの「組織構造」や「作業手順」に着目する人もいるが、あなたは優秀なチームづくりの秘訣は、各自が得意なことを充分にできるような、強みに基づく配役である、ということを本能的に知っている◆
レス・T(接客業、マネジャー)
カールは最も優秀な部下の一人ですが、それでも私たちは毎週顔を合わせるようにしています。
ちょっとした激励のことばをかけて、仕事の様子をきいてやるだけのことなんですが。
でも、それだけのことで、彼はまた意欲を燃やすんです。グレッグのほうは、そうしょっちゅう話し合いの場を持つのを好まないタイプなので、わざわざ呼びつけるようなことはしません。
顔を合わせるのは、私のほうに用事があるときくらいで、彼から何か言ってくることはまずありません
マーシャ・D(出版社重役)
登場人物の頭の上に丸で囲って書かれる台詞、漫画の吹き出しってあるでしょ?
自分のオフィスを出て、まわりを見渡すと、職場のみんなの頭の上にそれと同じようなものが見えることがよくあるんです。その人が何を考えてるかわかるんですよ。
変に聞こえるのはわかるけど、でも、私にはそういうことがあるんです
ここからはそれぞれの強みを持つ人の活かし方についてまとめてみます。
このエントリをお読みの方にはこっちの方が役に立つと思います(・∀・)
慎重さを強みとする人の活かし方
- 即断が要求されるポジションにこの人を就かせてはならない。自分だけの裁量で決定を下すことを好まないからだ。
- だから、じっくり検討するより先に行動を起こしがちなチームやグループに加える。必ずいい影響を及ぼして、そのチームやグループに欠けていた慎重さや、先を見越す能力が現れるようになるだろう。
- 物事を考える際、この人は細部に至るまで熟考する。だから、決定を下さなければならないときには、この人に頼み、計画を頓挫させる可能性のある要因を私的してもらうといい。
- この人は契約の交渉の場で才能を発揮する。特に第一線には立たず、後方から援助する立場に置かれると、並はずれた手腕を見せる。職域を脱しない範囲で頼むといい。
- この人には、接客や企業外部の実力者などとのパイプ役、企業に有益な人脈づくりといった仕事は向かない。その種の職務では、感情を表に出す必要があるため、対応しきれないのだ。
- 「人を見る眼」は非常にすぐれており、人間関係を築く上でその才能を発揮する。だから、所属を次々と買えるのはあまり望ましくない。仕事をともにする同僚が有能で信頼に値する人物かどうか、この人は何よりまずそのことを確認しようとする。そうした作業にはどうしても時間がかかる。
- この人はマネジャーになっても部下を必要以上に誉めることはない。だから、もしこの人が賞賛のことばを口にしたら、額面どおりに受け取ってまずまちがいはない。
学習欲を強みとする人の活かし方
- 状況が刻々と変化する分野で、その変化に即応しなければならない職務を任せる。そうした変化を自分の能力に対する挑戦と見て、意欲を燃やすタイプだ。
- この人は、そうする義務があろうとなかろうと、新たな事実や技術や知識を貪欲に身につけようとする。だから、学習により適した環境を求めて、あなたの企業を離れていかないように、この人が自由に学習できて、モチベーションを維持できる方法をあれこれ考えるといい。ただし、必ずしも昇進を望んでいるわけではないということを忘れないように。この人にとっては学習することそれ自体に意義があるのだ。学習の成果ではなく学習のプロセスそのものがこの人を活性化させるのである。
- 学習の進捗状況を見守り、そのつど到達したレベルを明確にする。そして、その進歩に対しては賞賛のことばをかける。
- 同じ分野の第一人者のそばで仕事をさせ、学習欲が刺激される環境に置く。
- 企業内の討論会やプレゼンテーションを取り仕切るよう促す。人に教えることほど自らが学習できる機会もないからだ。
収集心を強みとする人の活かし方
- 天性の収集心を活かし、企業にとって重要な問題を調査させる。この人は調査を通じて知識が増えることに喜びを覚えるタイプだ。
- 収集心以外のきわだった資質にも眼を向ける。成長促進にもすぐれているようなら、指導者や教育係としても手腕を発揮し、実話や寓話を織り交ぜた求心力のある指導をしてくれること請け合いである。
- インターネットを積極的に利用させる。必要と思われる情報はすべて集めてくれるだろう。集めた情報はすべてが即座に役に立つとはかぎらないが、情報収集はこの人の自尊心を高めるのに必要な作業なのである。
- 集めた情報を蓄積するシステムづくりを促す。システムが完備していれば、ときに応じて必要な情報を確実に得ることができる。
- 会議に出る際には必ずこの人に情報を求める。そして、折りを見て「きみにはわれわれが必要とする情報が初めからわかってるみたいだね。正直なところ、驚いている」といったような賞賛のことばをかける。
調和性を強みとする人の活かし方
- この人はできるかぎり争いごとから遠ざけたほうがいい。ほぼ確実に衝突が起きると予測される会議には初めから出席させないことだ。出席者同士が対立している状態では、この人は才能を活かすことができない。
- お互い合意の上で仕事手順を決め、その合意について定期的に話し合う場を持つ。この人と同じように調和性にすぐれた人たちとともに仕事をさせるとよい。まわりから支持されているとわかると、より集中し、より生産的で、より創造的な力を発揮する。
- 意見が割れる事柄についてこの人と話し合うのは時間の無駄だ。この人は相手の意見を変えるための議論を好まない。話し合うなら、はっきりとした対策が可能なことに的を絞るといい。
- 意見が対立し、歩み寄りが見られない場にこの人の存在は欠かせない。意見の対立を解消する手立てを必ずしも見つけてくれるわけではないが、同調できる点を見つける手助けにはなる。それで得られた同意点は、そこからまた新たに始める生産的な仕事の共通基盤になるだろう。
- この人は常に自分が何をしているかしっかりと把握しておきたいと思っている。だから、当人の行動を裏づけるもの(専門家の意見は効果的だ)をできるだけ提供してあげるといい。
個別化を強みとする人の活かし方
- 数多くのポジションにそれぞれだれを据えるか決定する人事会議には、この人が欠かせない。候補者一人ひとりの強みと弱みとが冷静に判断できるからだ。
- 企業の生産性向上のための手助けもこの人から借りるといい。だれに対しても強みと弱点とを基準に適材適所を考えてくれるからだ。
- 必要に応じて、社内の研修を担当させたり、少人数の新入社員の教育係を任せる。この人は一人ひとりに適した指導法を見きわめる能力に長けている。
本書のいいところは、
ただ強みを的確に指摘してくれるだけでなく、
そのまま具体的なアクションにまで移せるところかなと思います。
自分としても周囲の方々にどう使ってもらうかを考えて今後に活かしていきたいと思います。
長文にもかかわらず、
最後までお読みいただきありがとうございました。