scaffoldのコードを読む(その1)
scaffoldした際に、引数で指定される各フィールドの型によって自動的に決まるwebのコントロールを、自分の都合の良いように変えてみたいと思います。その為に、scaffoldに関連するコードを読んでみます。
前回railsからコピーしてきたtemplateから、view_edit.html.erbを見てみます。
<h1>編集 <%= singular_name %></h1> <%% form_for(@<%= singular_name %>) do |f| %> <%%= f.error_messages %> <% for attribute in attributes -%> <p> <%%= f.label :<%= attribute.name %> %><br /> <%%= f.<%= attribute.field_type %> :<%= attribute.name %> %> </p> <% end -%> <p> <%%= f.submit 'Update' %> </p> <%% end %> <%%= link_to 'Show', @<%= singular_name %> %> | <%%= link_to 'Back', <%= plural_name %>_path %> </macro:code> attribute.field_typeによって、コントロールが決まる仕組みになっています。field_typeは以下のようになっていました。 [rails-2.3.2/lib/rails_generator/generated_attribute.rb] >|| def field_type @field_type ||= case type when :integer, :float, :decimal then :text_field when :datetime, :timestamp, :time then :datetime_select when :date then :date_select when :string then :text_field when :text then :text_area when :boolean then :check_box else :text_field end end
変数typeは、script/generate scaffoldの引数に指定する「名前:sql_type」のsql_typeになります。
ちなみに、同ファイルにはdefaultというメソッドが含まれており、以下のようになっています。
def default @default ||= case type when :integer then 1 when :float then 1.5 when :decimal then "9.99" when :datetime, :timestamp, :time then Time.now.to_s(:db) when :date then Date.today.to_s(:db) when :string then "MyString" when :text then "MyText" when :boolean then false else "" end end
先ほどのfield_typeメソッドの定義から、scaffoldの引数にoneday:dateと指定すると、「f.date_select :oneday」というコードが生成されます。
このfという変数は何かとform_forやその先のfields_forを辿っていくと、デフォルトではActionView::Base.default_form_builder(=FormBuilder)のインスタンスになります。
[actionpack/lib/action_view/helpers/form_helper.rb]
def fields_for(record_or_name_or_array, *args, &block) ... builder = options[:builder] || ActionView::Base.default_form_builder yield builder.new(object_name, object, self, options, block) end
上記コードより、指定されたsql_typeによって任意のwebのコントロールを配置するには、カスタムFormBuilderを作ってform_forのoptionsに:builderを明示するか、FormBuilderの各メソッドを上書くことにより実現できそうです。