2

1.) モデルと直接やり取りしないコントローラー アクションを作成することは可能ですか? (つまり、解析するファイルをアップロードしてから、DB モデルに追加します)

2.) コントローラの操作順序は? コントローラーのアクションがビューをインスタンス化し、ユーザーが入力した params 変数に反応する方法がわかりません。

誰かがこれを説明してくれませんか、ありがとう。

パート II - モデルのないフォームのルーティング

したがって、現在のアップロード フォームには、parse_upload アクション (upload.html.erb ビューでアップロードされたファイルを操作する) にルーティングするアップロード アクション (ユーザーからファイルを取得する) の 2 つのアクションがあります。

ルート.rb:

::Application.routes.draw do
    devise_for :users
    resources :revenue_models do
        get 'upload', :on => :collection
        put 'parse_upload',:on => :collection
    end
    root :to => "home#index"
 end

行動:

# UPLOAD multiple files from an Exel Doc; integrate them accordingly
def upload
    @uploaded_doc = { :workbook => RubyXL::Parser.new }     
end
# Parse the uploaded file
def parse_upload
@worksheet = RubyXL::Parser.parse(params[:uploaded_doc]       
                  [:workbook]).worksheets[0].extract_data
end

upload.html.erb (このアップロード フォームのパラメーターを parse_upload アクションにプッシュするようにしたい)

<%= form_tag(:url => {:controller => "revenue_models", :action => "parse_upload"}, :html => {:method => "put", :multipart => true}) do %>
    <%= file_field(:uploaded_doc, :workbook) %>
<%= submit_tag("Upload") %>     
<% end %> 

現在、ファイルを送信するとルーティング エラーが発生します: [POST] "/revenue_models/upload" に一致するルートがありません

アップロード フォームから [parse_upload] アクションにルーティングするまで、すべてが正常に機能していると想定しています。以下のMOREの回答に従ってみましたが、私の場合、既存のモデルを中心としたフォームを使用していないため、少し迷っています. 問題が何であるかの手がかりはありますか?前もって感謝します。

4

2 に答える 2

3

1) はい、確かに、コントローラーはどのモデルでも動作する必要がまったくないか、何千ものモデルで動作できます。足場と混同しないでください。コントローラーが通常モデルの上にあるという事実は、コントローラーの主な責任はそのモデルと対話することですが、それは規則ではありません。

2) ラックが HTTP スタックで終了した後、ルーティング (config/routes.rb で定義) にディスパッチされ、ルーターはそれをそのファイルで指定したコントローラー/メソッドにディスパッチします。現在アプリ内のすべてのルートを表示したい場合は、「rake routes」と入力します。

コントローラーは、ラックからパラメーターを受け取ります。http リクエスト パラメータはハッシュにきちんとまとめられ、params() メソッドで簡単にアクセスできる方法で送信されます。コントローラーは、パラメーターを読み取る以外に何もしません。

ビューに関しては、コントローラーによってディスパッチされません。コントローラーが render()、render_to_string()、render_with() などを呼び出すと、適切なビュー テンプレートとレイアウト (どちらも指定できるか、コントローラーによってデフォルト設定されている) が読み込まれ、処理されます (に変換されます)。 HTTP 応答を介して送信される文字列)。ここでの唯一の魔法は、コントローラーのインスタンス変数がビューで使用できるようになることです (ビュー自体がインスタンス変数として使用できます)。

これでいくつかの問題が解決したことを願っています.. :)

于 2013-02-20T20:03:14.443 に答える
2

1)はい、絶対に、コントローラーの「アクション」はモデルを処理する必要はありません。

ThingController < ApplicationController
  def status
    @status = system("#{Rails.root}/lib/mystatusscript");
  end
end  

URLがサーバーに到達するとアクションが呼び出され、ルーティングテーブルが参照され、コントローラーとアクションが決定されます。したがって、これをroutes.rbに入れると:

match "/whatever" => "things#status"

とタイプ

http://localhost:3000/whatever

ThingsController(app / controllers / things_controller.rb)のステータスアクションが呼び出されます。

次に何が起こるか、デフォルトでは、他に何もするように指示していないため、railsはapp / views / things / status.html.erbを検索し、それをレンダリングします。

The stats is <%= @status %>

しかし、あなたはそれを防ぎ、レールに何か他のことをさせることができます、可能な例:

ThingController < ApplicationController
  def status
    @status = system("#{Rails.root}/lib/mystatusscript");
    render :js=>"$('#status_retreived').show();"
  end
end  

ThingController < ApplicationController
  def status
    system("#{Rails.root}/lib/do_something_server_side");
    render :nothing=>true
  end
end  

ThingController < ApplicationController
  def status
    @status = system("#{Rails.root}/lib/mystatusscript");
    render action=>:edit
  end
end  

追加

フォームを作成して、何が起こるか見てみましょう

app / views / things / edit.html.erbにこれがあるとしましょう:

<%= form_for @thing do |f| %>
  <%= f.input :name %>
  <%= f.submit %>
<% end %>

これらのルートがroutes.rbにあるとします。

get '/things/:id/edit' => 'things#edit'
put '/things/:id/update' => 'things#update'

そして、あなたのコントローラーは:

def update
  @thing = Thing.find(params[:id])
  @thing.attributes = params[:thing]
  @thing.save
end
def edit
  @thing = Thing.find(params[:id])
end

これがフローです。アプリを「/things/ 100/edit」でヒットします。

編集アクションが呼び出され、インスタンス変数@thingがIDが100のレコードに設定されます。次に、edit.html.erbビューがレンダリングされ、名前フィールドの編集画面と送信ボタンが表示されます。

「送信」をクリックすると、「/ things / 100/update」に移動します。

ルートの定義方法'/things /:id / update'により、更新アクションに入ると、params [:id]には100が含まれ、params [:thing]にはフォームによって投稿されたものが含まれます。つまり、パラメータには次のものを含めることができます。

params[:thing][:name]
params[:thing][:city]
....
params[:thing][:zip]

IDはparams[:id]に抽象化され、フォームデータはparams [:thing]にあります。

もっと

railsはあなたのために多くの自動URL生成を行います、それはそれについて非常に賢いです、例えば、edit.html.erbで、あなたはこれを持っています:

<%= form_for @thing do |f| %>
  <%= f.input :name %>
  <%= f.submit %>
<% end %>   

生成されたHTMLを見ると、次のようになります。

<form id="edit_thing_100" method="put" action="/things/100/update"> 

レールは、作成ではなく更新を行うことをどのように知っていましたか?@thingをチェックし、以前にデータベースにすでに保存されていることに気付いたため、これは新しいレコードではないため、更新である必要があります。

したがって、ビューでは通常、リンクや送信ボタンなどを介してサーバーに送信されるさまざまなURIを作成します。それらがroutes.rbで検索されると、適切なコントローラーで適切なアクションが呼び出されます。

ファイルのアップロード

思ったより簡単です。まず、ファイルアップロードフィールドを追加し、フォームを少し変更する必要があります。

<%= form_for @thing do ,:html=>{:multipart=>true} |f| %>
  <%= f.input :name %>
  <%= f.file_field :upload %>
  <%= f.submit %>
<% end %>   

これで、更新アクション内でこれを行うことができます。

def update
  filename = params[:thing][:upload].original_filename
  filetype = params[:thing][:upload].content_type
  filedata = params[:thing][:upload].read

  File.open("#{Rails.root}/filestorage/#{filename}","wb") { |f| f.write(filedata) } 

  @thing = Thing.find(params[:id])

  @thing.attributes = params[:thing]
  @thing.uploadstoredin = "#{Rails.root}/filestorage/#{filename}"
  @thing.save
end

フォームをマルチパートにし、属性:uploadをfile_fieldとして宣言したため、paramsが投稿されると、:upload paramには3つの追加メソッド(original_filename、content_type、read)があります。RailsMAGIC!

于 2013-02-20T20:10:37.837 に答える