1
votes

I would like the submit button action to execute a rails method or a rake task on the server side. The task copies the records from one model to another. I intend to add the button to the bottom of the index view of the pages controller.

I've read some posts but still can't figure out how to use the remote_function. Also tried using :onclick => :make_assets but nothing happens. Thanks

e.g. radio_button :model, :method, :onclick => remote_function(:controller => 'some', :action => 'action')

lib/tasks/move_photo.rake

namespace :db do
desc "Move records from photos to assets"
task :movephoto => :environment do
Rake::Task['db:migrate'].invoke
make_assets
end
end

def make_assets
Photo.all.each do |photo|
newasset = nil
newasset = Asset.create!(:user_id => photo.user_id,
:image => photo.image)
photo.destroy unless newasset.nil?
end
end

/app/controllers/photos_controller.rb

def make_assets
Photo.all.each do |photo|
newasset = nil
newasset = Asset.create!(:user_id => photo.user_id,
:image => photo.image)
photo.destroy unless newasset.nil?
end
end

/app/views/photos/index.html.erb

<%= will_paginate %>


<%= will_paginate %>
<%= submit_tag 'Approve', :onclick => remote_function(:controller => :photos, :action => :make_assets) %>

4

4 Answers

2
votes

Executing a rake task from the controller is an exceedingly bad idea.

Never give an untrusted client access to your system.

That said, it seems like what you really want to do is something that fits well within the parameters of a controller action. I think you're missing the :url hash in the remote function call:

<%= submit_tag 'Approve', :onclick => remote_function(:url => {:controller => :pages, :action => :make_assets}) %>
1
votes

you can run a rake command, its like running a dos or shell command from rails.But as I can see you want run rake db:migrate and then some other task and as per my understading of rails, you need to restart the application after running such rake tasks so that would make a problem if you are running rake command for current running application.

For other stuff i.e. copy records from one model to another, you can have a class method in Model(Photo model in your case) and can invoke that method in controller's action which invoked from UI. The code might look as

photo Model

class Photo < ActiveRecord::Base

 def self.make_assets
  Photo.all.each do |photo|
   newasset = nil
   newasset = Asset.create!(:user_id => photo.user_id,
   :image => photo.image)
   photo.destroy unless newasset.nil?
  end
 end

end

photo controller

def make_assets
 Photo.make_assets
end

view side you have various option to invoke make_assets action

1) link_to

<%=  link_to "Make Assets", 
    url_for( :action => "make_assets", :controller=> :photos ),:remote=>true %>

2) button_to

<%= button_to "Make Assets", 
    url_for( :action => "make_assets", :controller=> :photos ),:remote=>true %>

3) form_tag

 <% form_tag(:url => url_for(:action => "make_assets", :controller=> :photos),:remote => true) do -%>
    <div><%= submit_tag 'Save' %></div>
  <% end -%>
1
votes

Yeah, rake tasks are not intended to be run from a controller. Consider refactoring and extracting take task functionality to separate method. Then you can call this method both from the rake task and the controller action.

To be honest, i wanted to debug my rake task this way before realizing the need to to refactor.

As for your code to work you have to load tasks manually, and don't forget to reenable the task in order to run it second time.

require 'rake'

Rake::Task.clear # necessary to avoid tasks being loaded several times in dev mode
Sample::Application.load_tasks # providing your application name is 'sample'

class RakeController < ApplicationController

  def run
    Rake::Task[params[:task]].reenable # in case you're going to invoke the same task second time.
    Rake::Task[params[:task]].invoke
  end

end

You can require 'rake' and .load_tasks in the initialization section.

0
votes

You can try with the button_to helper for calling the controller action:

<%= button_to 'Approve', :controller => :pages, :action => :make_assets %>

add the remote => true parameter if you want to do the request via Ajax