Rubyist SNS のURL

投稿者 nanki 2007-01-22 18:34:00 GMT

勉強会の途中で最新版にupdateして、コミュニティの新規作成機能でも実装しよう、と思って、 /community/new というURLを使おうとしたら、/community/:community_name という風にコミュニティに名前でアクセスする仕様になっているために使えなくなっている、どうしましょうか。

という話を、懇親会でかずひこさんとしていました。

解決方法はいくらでもあるけど、routes.rbで頑張りすぎると、機能が増える度にURLを考えないといけないし、Rails アプリケーションのサンプルコード的な、というお役目も考えると、お約束を積極的に破る、というのはどうなんだろう、ということもあって、ちょっと迷う。

acts_as_sluggableというのを使うと、link_toの結果が、/community/show/1-ruby-kansai みたいになるそうなんですが、これなんてどうでしょう。

参考

Rubyist SNS Trac


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です。


夜露死苦変換

投稿者 nanki 2006-06-05 02:33:00 GMT

IMEが「ぐれっぷ」を「具烈婦」に変換したのをきっかけに。

ひらがなのみ対応。「ー」はだめ。

面白いのを見つけた人はコメント欄に残していってくださるとうれしいです。

るびいすと → 流美異酒人


Hash.new

投稿者 nanki 2006-06-01 06:06:00 GMT

Hash.new{|hash, key| ...}を悪用してフィボナッチ数列を返す変なハッシュ。

fib = Hash.new{|h, k| h[k] = h[k-1] + h[k-2]}.update(0 => 0, 1 => 1)

p fib[30] # 832040

「Rubyプログラミング入門」には

def (Fib = [0, 1]).[](n)
  super || Fib[n] = Fib[n-1] + Fib[n-2]
end

p Fib[30] # 832040

というのが載っていて、こっちの方がかっこいい。

あと、Hash.new{[]} という形が面白いのでよく使います。グループ化する時とか。

Ruby覚え立ての頃、初々しいコード。

a = {}
zip_address.each do |zip, address|
  if a[zip] then
    a[zip] << address
  else
    a[zip] = [address]
  end
end

unlessの後置構文とか覚え出して。

a = {}
zip_address.each do |zip, address|
  a[zip] = [] unless a[zip]
  a[zip] << address
end

条件分岐使わなくなる。

a = {}
zip_address.each do |zip, address|
  a[zip] ||= []
  a[zip] << address
end

お気に入り。

a = Hash.new{[]}
zip_address.each{|zip, address| a[zip] <<= address}