最近のDBはミラーリングやレブリケーションが当たり前にされてるので
DBにバイナリで画像格納ってのはよくある方法だと思う。
概要
1.controllerでバイナリデータ以外をselect
2.view側でurl_forによりcontrollerで定義した画像表示actionを指定
3.view側のimage_tagで表示
4.通常のhtmlレンダリング時に、画像表示actionがリクエストされると
controllerのsend_dataでは、id毎にバイナリデータを検索してviewに返す
この流れでは、画像毎にselectが走るが
まぁ、致し方ないか。
controller
selectオプションでバイナリデータ以外の項目を取得。
def index #@images = Image.all @images = Image.all(:select => 'id, name, updated_at') respond_to do |format| format.html # index.html.erb format.xml { render :xml => @images } end end
def get_image @image = Image.find(params[:id]) send_data(@image.image, :disposition => "inline", :type => "image/png") end
view
<% @images.each do |image| %> <tr> <td><%=h image.name %></td> <td><%= image_tag(url_for(:action => 'get_image', :id => image.id), :size => '100x100')%></td> <td><%= link_to 'Show', image %></td> <td><%= link_to 'Edit', edit_image_path(image) %></td> <td><%= link_to 'Destroy', image, :confirm => 'Are you sure?', :method => :delete %></td> </tr> <% end %>
あれ?
生成されたhtmlを見ると
image_tagで通常表示した際に付く、画像のタイムスタンプが無い。
そうか、バイナリだもんな。
これだと、タイムスタンプによるキャッシュが使えない。
なんとかDB更新日時渡せないかな、と↓を思い返しながら思案。
passengerのcss - うんたらかんたらRuby - Rubyist
image_tagをオーバーライドしてやってみた。
view側でaddsrcオプションを指定。
<%= image_tag(url_for(:action => 'get_image', :id => image.id), :size => '100x100', :addsrc => image.updated_at.to_i.to_s) %>
helper
added start から addes endの箇所。
addsrcを追記して、最後に消してみた。
#override method #actionpack-2.3.5/lib/action_view/helpers/asset_tag_helper.rb def image_tag(source, options = {}) options.symbolize_keys! options[:src] = path_to_image(source) options[:alt] ||= File.basename(options[:src], '.*').split('.').first.to_s.capitalize if size = options.delete(:size) options[:width], options[:height] = size.split("x") if size =~ %r{^\d+x\d+$} end if mouseover = options.delete(:mouseover) options[:onmouseover] = "this.src='#{image_path(mouseover)}'" options[:onmouseout] = "this.src='#{image_path(options[:src])}'" end # added start if options[:addsrc] if /\?/ =~ options[:src] options[:src] << "#{options[:addsrc]}" else options[:src] << "?#{options[:addsrc]}" end options.delete(:addsrc) end # added end tag("img", options) end
んで
どうなんでしょう。こういうやり方って。
使用箇所を最小限にするならありなんでしょうか?
file_columnとか使うと幸せになれるんだっけ?
2010/03/12追記
viewでurl_forを使って画像呼出しメソッド呼んでたけど
image_tag("/get_image/#{id}", options) みたいに書けるようだ。
これでもいいね。