アップロードの管理機能を追加 その2

ファイル修正日時の記録

Displayモデルが管理するレコードを修正した日時を、Csvモデルの対応するレコードに記録したい。created_atでは、Csvモデルの修正日時になってしまうので、ちょっと工夫が必要だ。以下のようにしてみた。

  • Displayモデルが管理するテーブルに対してcreate、update、destroyが実行されたら...
  • Csvモデルのfile_nameが上記テーブル名と同じレコードを検索して、現在時刻を記録する。
# ---------- app/models/display.rb ----------

require 'ajax_scaffold'

class Display < ActiveRecord::Base
...(途中省略)...
  
  after_save    :csv_file_updated_at
  after_destroy :csv_file_updated_at
  
  def csv_file_updated_at
    csv = Csv.find_by_file_name(Display.table_name)
    csv.update_attribute(:file_updated_at, Time.now)
  end
...(以下省略)...
  • Csvモデルのfile_nameに記録した文字列を、Displayモデルのテーブル名として利用するように変更しておいた。(Csvモデルのfile_name = Displayモデルのテーブル名)
# ---------- app/models/csv.rb ----------
class Csv < ActiveRecord::Base
...(途中省略)...  
  # Tempfileオブジェクトをインスタンス変数に保存する。
  # new()や、update_attributes()の時、呼び出される。
  def tempfile=(file)
    return if file.nil? || file.size == 0
    @file = file
    # 先頭に_を付加する。(CSVファイルとアプリケーションのテーブルを区別するため。)
    self.file_name = file.original_filename.gsub(/^(.)|\W/, '_\1')
    self.file_size = file.size
  end
  
  # テーブルを追加する。
  def create_csv_table
    ActiveRecord::Migration.create_table csv_table do |t|
      csv_columns.each do |f|
        t.column f, :string
      end
    end
  end
  
  # テーブル名を返す。
  def csv_table
    # File.basename(self.file_name, ".*").gsub(/^(.)|\W/, '_\1')
    # 以下のように変更した。
    self.file_name
  end


以上で、CSVファイルを新規作成、編集、削除した時の最終日時が記録されるようになった。

編集可能フラグの実装

編集可能フラグ(フィールド名:editable)には、「編集可能(true)」「表示のみ(false)」の値が記録されている。編集可能フラグの値を管理しているのはCsvモデル、CSVファイルを編集するのはDisplayモデルの仕事、と分かれている。なので、Csvモデルから、Displayモデルに編集可能フラグの情報を渡してあげる必要がある。

  • パラメーターとして、:editable => listd.editableを追加した。
<%# ---------- app/views/csvs/_listd.rhtml ---------- %>
<!--[:]-->
<tr>
  <%# リストデータの表示 %>
  <td><%= link_to h(listd.file_name), :controller => 'displays', :action=>'list', 
                  :table => listd.csv_table, :editable => listd.editable %></td>
...(以下省略)...
  • ajax_scaffoldで、Create New、Edit、Deleteの表示を制限するため、if params[:editable]を追記した。
<%# ---------- app/views/displays/component.rhtml ---------- %>

<% if @show_wrapper %>
<div class="back"><%= link_to '<< Back', :controller => 'csvs' %></div>
<div id="<%= params[:scaffold_id] %>" class="ajax-scaffold">
  <div id="<%= scaffold_content_id(params) %>">
<% end %>
    <div class="ajax-scaffold-header">
      <div class="actions">
        <% new_params = params.merge(:controller => '/displays', :action => 'new') %>
        <%= loading_indicator_tag(new_params) %>
        <%= link_to_remote "Create New",
          { :url => new_params,
            :loading => "Element.show('#{loading_indicator_id(new_params)}');" },
          { :href => url_for(new_params),
            :class => "create" } if params[:editable] %><%# <------追記 %>
      </div>
      <h2><%= Display.table_name %></h2>
    </div>
...(以下省略)...
<%# ---------- app/views/displays/_display.rhtml ---------- %>

...(途中省略)...
          <% edit_options = @options.merge(:action => 'edit') %>
          <%= link_to_remote "Edit",
                         { :url => edit_options,
                           :loading => "Element.show('#{loading_indicator_id(@options)}');" },
                         { :href => url_for(edit_options) } if params[:editable] %><%# <------追記 %>
        </td>
        <td>
          <% delete_options = @options.merge(:action => 'destroy') %>
          <%= link_to_remote "Delete",
                         { :url => delete_options,
                           :confirm => 'Are you sure?',
                           :loading => "Element.show('#{loading_indicator_id(@options)}');" },
                         { :href => url_for( delete_options ) } if params[:editable] %><%# <------追記 %>
        </td>
      </tr>
    </table>
  </td>
</tr>
  • パラメーターを保持するために、:editable => params[:editable]を追記した。(これが無いと、newやeditで編集直後、常に「表示のみ」の扱いになってしまう。)
# ---------- app/views/displays/new.rjs ----------

@options = { :scaffold_id => params[:scaffold_id], :action => "create", :id => generate_temporary_id, 
             :table => params[:table], :editable => params[:editable] }
# ---------- app/views/displays/edit.rjs ----------

@options = { :scaffold_id => params[:scaffold_id], :action => "update", :id => params[:id], 
             :table => params[:table], :editable => params[:editable] }


以上で、「表示のみ」のCSVファイルでは、Create New、Edit、Deleteのリンクを表示しない状態になる。