Rails勉強会@関西6

投稿者 nanki 2007-01-22 05:51:00 GMT

土曜日は、Rails勉強会に行ってきました。

今回は、初心者レッスンの担当。

朝8時に起きて準備するはずが、前日5時くらいまで(というか、三時間前まで)いろいろやっていたので、目覚まし時計の思いも届かず、2時間寝坊。 ひげを剃るのも会場で。 11時到着に合わせて計算していたので、なんとか12時前にはたどりつけたけど、あせったなぁ。

発表は、なんとか終了。 途中で場内を回ってみると、思いの外、進み具合がバラバラだったので、最後の部分は演習時間を延長してカット。

なにから解放されたのか、昼御飯は食べる気も起こらなかったのに懇親会まではずっとお腹が鳴りっぱなしなのでした。

終わってから気がついたけど、初期のRails勉強会のように、教科書になるような本を写経とかでもいいんじゃないか、と思えてきた。
毎回、目的のテーマにたどり着くまでに、ActiveRecord, scaffold の道を進まねばならないので、なんとも大変。 三回目なので、シリーズ化はまだ止められそうだし。

「RailsでXML-DBにチャレンジ」by モバイル通信兵さん

おもしろそう。 DB2要求されるのが、ちょっとハードル高め。 使えそうな場所を探してみようっと。

「Rubyist SNS の実装について」by かずひこさん

最近コミットできてなくて申し訳ないです。 会場で、updateしていつものように一人で友達作って・・・
この作業がいつも寂しい。

「rails tips」by 氏久さん

<%=h %>は、エディタのショートカットで出せるように設定していて、<%= %> にするには、hを削らないといけない、という安全スイッチがあるので、少人数での開発の場合はまあいいかな。 jitor は楽しそう。

「やさしいRailsの育て方(仮題)」by 西和則さん

DBモデリング?のお話。 火星エステ理論なる判別法で、本質的な項目を洗い出せ!

火星の鈴木さん(だっけ?)で何故か火星年代記を思い出してしまった。

懇親会は、内装がゴージャスなお店。

二次会では、非カラオケチームに合流しようとして連絡をしたら、途中で携帯の電池が切れてしまって、結局合流できなかった・・・。 今朝、僕の目を覚まそうとして、一時間に渡ってブルブルしてたはずだから、当然なのかも。

なので、はぐれ組三人で、駅前のサンマルクカフェで、お話しました。


ActiveRecord - フォーマット

投稿者 nanki 2006-12-27 21:09:00 GMT

小分けにしないとサーバが止まる・・・

model_formatter
  • 特定のカラムを、フォーマット付きでアクセス。
  • formatted_weight で、フォーマット済みのweightにアクセス。
  • フォーマット済み属性の名前は、:formatted_attr, :prefixで変更。
  • class Widget < ActiveRecord::Base
    # FormatInteger という名前のFormatterでフォーマットを指定
    # :boolean, :currency, :decimal, :integer, :percent, :phone が定義済み
    # :as には、Formatterのインスタンスも指定できる
    format_column :weight, :as => :integer

# Procを使って format_column :weight,

<span class="symbol">:formatted_attr</span> =&gt; <span class="symbol">:formatted_weight</span>,
<span class="symbol">:options</span> =&gt; {<span class="symbol">:delimiter</span> =&gt; <span class="string"><span class="delimiter">'</span><span class="content">,</span><span class="delimiter">'</span></span>},
<span class="symbol">:from</span> =&gt; <span class="constant">Proc</span>.new{|attribute, options| ... },
<span class="symbol">:to</span>   =&gt; <span class="constant">Proc</span>.new{|str, options| ... }

# ブロックによる定義も format_column :weight do

<span class="keyword">def</span> <span class="function">from</span>(attribute, options)
  <span class="comment"># ...</span>
<span class="keyword">end</span>

<span class="keyword">def</span> <span class="function">to</span>(str, options)
  <span class="comment"># ...</span>
<span class="keyword">end</span>

end end

w = Widget.new(:weight => 12345) w.formattedweight # => 12,345 # 書き込みもできる! w.formattedweight = 54,321 w.weight # => 54321

auto_convert_fields
  • attribute=を定義。
  • class MyModel < ActiveRecord::Base
    # name=, :text= の前に、TextHelper#striptags をはさむ。
    autoconvert :name, :text, :with => :strip_tags

# 同じ auto_convert :name, :text do |value|

strip_tags(value)

end end


:yの悲劇

投稿者 nanki 2006-12-21 18:51:00 GMT

GPS情報を格納するのに、

class Entry < ActiveRecord::Base
  has_one :location
end
  
class Location < ActiveRecord::Base
  # 実際にはGeometry型で格納するので、アクセサを定義
  def x
    point.x
  end
  def y
    point.y
  end
end

こんなモデルを作ると・・・

$ script/console
>> entry = Entry.find(:first)
>> entry.location.x
=> 135.0
>> entry.location.y
=> 35.0
>> entry.location.send :x
=> 135.0
>> entry.location.send :y
ArgumentError: wrong number of arguments (0 for 1)
        from (irb):35:in `y'
        from (irb):35:in `send'
        from (irb):35

xは大丈夫なのにyはだめ?

yの正体は、pのようにyamlを吐くprivate method、Kernel#y in yaml.rb。 何故だ?

entry.location の中身は、実はAssociationProxyで、ActiveRecordのソースを見るとこんな風になっている。

# lib/active_record/associations/association_proxy.rb
module ActiveRecord
  module Associations
    class AssociationProxy #:nodoc:
      attr_reader :reflection
      alias_method :proxy_respond_to?, :respond_to?
      alias_method :proxy_extend, :extend
      instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?|^proxy_respond_to\?|^proxy_extend|^send)/ }

entry.location.send :x すると、AssocationProxy#xが無いのでtargetにsendされるが、entry.location.send :y だと、Kernel#yが見つかってしまうのか・・・

当然entry.location.target.send :y だとうまくいく。

Ruby1.9 だとsendの仕様が違ってうまくいきそう。


svn:externals のリビジョン固定

投稿者 nanki 2006-12-03 11:01:00 GMT

Railsで $ script/plugin install -x したプラグインのリビジョンを固定するには、

$ svn propedit svn:externals vendor/plugins/

として、

plugin_name  -r150  svn://example.com/path

とやればよいらしい。

参考

subversion - 外部定義


Rails Plugin - View系2

投稿者 nanki 2006-10-05 06:55:00 GMT
MenuEngine
  • DHTMLのメニューを作る。
  • # in config/environment.rb
    module ApplicationHelper
    include MenuHelper
    end

# in app/helpers/applicationhelper.rb module ApplicationHelper include MenuHelper end

*
module MenuEngine
  # UserEngineと連携
  # trueで許可されないcontroller/actionへのメニューが表示されなくなる
  config :accesscontrol, false
  # エフェクトの設定。element はメニューを指す。
  config :onshow, "new Effect.Appear(element);"
  config :onhide, "new Effect.Fade(element);"
end
*
module ApplicationHelper
  def my_menu

item0 = <span class="constant">MenuItem</span>.new(<span class="symbol">:text</span> =&gt;  <span class="string"><span class="delimiter">&quot;</span><span class="content">Users</span><span class="delimiter">&quot;</span></span>, <span class="symbol">:controller</span> =&gt; <span class="string"><span class="delimiter">&quot;</span><span class="content">user</span><span class="delimiter">&quot;</span></span>)
item1 = <span class="constant">MenuItem</span>.new(<span class="symbol">:text</span> =&gt;   <span class="string"><span class="delimiter">&quot;</span><span class="content">List</span><span class="delimiter">&quot;</span></span>, <span class="symbol">:controller</span> =&gt; <span class="string"><span class="delimiter">&quot;</span><span class="content">user</span><span class="delimiter">&quot;</span></span>, <span class="symbol">:action</span>=&gt;<span class="string"><span class="delimiter">&quot;</span><span class="content">list</span><span class="delimiter">&quot;</span></span>)
item2 = <span class="constant">MenuItem</span>.new(<span class="symbol">:text</span> =&gt; <span class="string"><span class="delimiter">&quot;</span><span class="content">Images</span><span class="delimiter">&quot;</span></span>, <span class="symbol">:controller</span> =&gt; <span class="string"><span class="delimiter">&quot;</span><span class="content">image</span><span class="delimiter">&quot;</span></span>)

item0.items &lt;&lt; item1
[item0, item2]

end end

*
<%= enginestylesheet "menuengine" %>
<%= enginejavascript "menuengine" %>
...
<%= menu :menu => my_menu, :layout => :vertical %>
* YAMLで設定する方法もある。


Rails Plugin - ActiveRecord拡張系2

投稿者 nanki 2006-08-29 16:24:00 GMT
acts_as_modified

# restore person.restore_attributes :only => :age person.age # 100

# clear person.clearoriginalattributes :only => :age

# dbと比較 person.modified?(:reload) # true

acts_as_bookmarkable

post.add_bookmark(Bookmark.new)

だけ。 * 構成はacts_as_commentableとほぼ同じ。

acts_as_commentable
acts_as_sluggable

urlfor :controller => "articles", :action => 'show', :id => @article # => "/articles/show/76-omg-my-cat-is-so-cute-lol" * toparam というメソッドを上書きしてるらしい。

acts_as_sequenced

class Customer < ActiveRecord::Base actsassequenced

<span class="comment"># 連番</span>
<span class="symbol">:column</span> =&gt; <span class="symbol">:customer_number</span>,
<span class="comment"># 有効範囲</span>
<span class="symbol">:scope</span> =&gt; <span class="symbol">:account</span>

end

class Job < ActiveRecord::Base actsassequenced :column => :job_number, :scope => :account endこれで、Account毎に連番が。 * プラグインの形では提供されてないので、コードをlib/以下にコピペして、environment.rbでrequireしてね。 * コードからは、削除して追加すると、過去の管理番号と重複する番号が割り当てられるように見える。(これはうれしくない) * acts_as_paranoid(削除フラグで削除したかの用に見せるプラグイン)と併用できるようになっていて、併用すればこの問題は起こらなさそう。

acts_as_most_popular

# すると、頻度の高い順に3個とってこられる。 Person.mostpopularnames # => ["Jajamaru", "Piccolo", "Porori"] * nameが複数形になるってどういうことよ。

acts_as_network

alice, bob = User.find([1,2])

# bobはaliceの友達です alice.connections << bob

# bobはaliceの2です alice.connections.pushwithattributes(bob, :role => 2) alice.connections.find(bob.id).role # => 2

# bobはaliceの友達ですか? alice.connections.include?(bob) # => true

# aliceは誰の友達ですか? alice.connections.all_in

acts_as_rateable

def self.down

drop_table <span class="symbol">:ratings</span>

end end *

class YourModel
  actsasrateable
end

# 5点をつける m.rate(5) m.rating = 5

# 5点 m.rating # => 5

# 最初に見つかった3点のもの YourModel.findbyrating(3) # 3点以上のもの全部 YourModel.findallbyrating(3..-1) # 1点または3-5点のもの全部 YourModel.findallbyrating([1,3..5])

acts_as_ratable

# currentuserが5点をつけました m.rateas(5, :by => current_user)

# currentuserによって付けられた点数 m.ratingby(current_user)

m.average_rating # => 平均点 m.raters # => 採点者 * 同じユーザが同じものに採点すると上書きされる。

acts_as_popular
acts_as_searchable
acts_as_rast_indexed
acts_as_ordered
acts_as_taggable
acts_as_versioned
acts_as_paranoid
acts_as_bitfield
acts_as_deque
acts_as_attachment
better_nested_set
acts_as_threaded
acts_as_ldapable
acts_as_habtm_list
acts_as_shellable
acts_as_enumerated

バーコード大作戦(予告編)

投稿者 nanki 2006-07-10 16:13:00 GMT

がーん。

バーコードペディア:Webカメラでスキャンできる製品情報コミュニティ - Engadget Japanese

以前からbarcoder.nuとしてやっていたところがコンセプトをちょっと変えてみた?よう。

半年くらい天日干しにしている社内プロジェクトがあって、それがちょうどこんなコンセプトなんです。

demo QuickTime:2.4MB

というわけで頑張って今月中にでもリリースします。と書いて、自分のお尻に火をつける。

点スイッチ有限会社の最初のサービスとしてリリースできるといいな。

リンク先がないのにリンクを張るのは、早く会社のサイトを作らなきゃ、というプレッシャーです。

あ、もちR on Railsです。


Rails Plugin

投稿者 nanki 2006-04-25 23:35:00 GMT

全部終わったら公開しようと思っていたけど、全く終わる気配がないので公開します。

今回は量が多いので分割しました。

全部見たい人は、 タグ:rails_pluginでどうぞ。


Rails Plugin - ActiveRecord拡張系

投稿者 nanki 2006-04-25 23:30:00 GMT
composite_primary_keys

class Road < ActiveRecord::Base belongsto :attribute, :foreignkey => [:attributecode, :meshcode] end

class Attribute < ActiveRecord::Base setprimarykeys :attributecode, :meshcode end

Road.find(:first).attribute #=> SELECT...WHERE roads.attributecode = attributes.attributecode and roads.meshcode = attributes.meshcode ...

pessimistic locking

Account.transaction do account = Account.find(:first) account.lock # ... end

で悲観的ロックができる。 * Edgeには取り込まれたっぽい。

has_many_polymorphs

class Cat < ActiveRecord::Base hasmany :eaterpetfoods, :as => :eater hasmany :petfoods, :through => :eaterpetfoods end

class EatersPetfood < ActiveRecord::Base belongsto :petfood belongsto :eater, :polymorphic => true end

class Petfood < ActiveRecord::Base hasmany :eaterpetfoods hasmany :eaters, :through => :eaterpetfoods # これができない end *

# hasmanypolymorphs
class Dog < ActiveRecord::Base;end
class Cat < ActiveRecord::Base;end

class EatersPetfood < ActiveRecord::Base belongsto :petfood belongsto :eater, :polymorphic => true end

class Petfood < ActiveRecord::Base hasmanypolymorphs :eaters, :from => [:dogs, :cats] end

* eaterが増える度にPetfoodを書き換えないといけないのがかっこよくない。

store_multiplied
force uppercase
ActiveCrypto
UpdateHabtmAttributes
allow_habtm_primary_key
userstamp

class ApplicationController < ActionController::Base before_filter do |c|

<span class="constant">User</span>.current_user = <span class="constant">User</span>.find(c.session[<span class="symbol">:user</span>].id) <span class="keyword">unless</span> c.session[<span class="symbol">:user</span>].nil?

end end

class Post < ActiveRecord::Base belongsto :createdby, :classname => "User", :foreignkey => "createdby" belongsto :updatedby, :classname => "User", :foreignkey => "updatedby" end

active form
riff
enforce_column_limits
validates_numericality_of
ActiveSearch
Spatial Adapter
settings
autoescape
deadlock_retry
calculations
guid
where
count_limit_associations
file_column
filters_column
filtered_column

Rails Plugin - 認証系

投稿者 nanki 2006-04-25 23:29:00 GMT
session_timeout
access_control
validates_captcha
account_location
acts_as_authenticated
login_engine
user_engine
ssl_requirement
security_extensions
sentry