How should I update one model (table) from a different controller (or model)
I have a generic import table that allows the loading of csv files into different columns in my import table. The same import table is used for multiple types of imports, so I don't process the individual fields until the user is ready and tells me where to process it.
So in this case I have an import table with many cells that I will use to create (or update) donors in my donors table. How do I send my import_table data associated with the import_table model and controller to the create method of my donors_controller?
the create method of my donors_controller:
def create
# need to find donor by id if given, else use find_or_create_by_blahblahblah
unless @donor = Donor.find_by_id(params[:donor][:id])
@donor = Donor.find_or_initialize_by_company_and_prefix1_and_first_name1_and_last_name1_and_address1(params[:donor])
end
if @donor.new_record?
respond_to do |format|
if @donor.save
format.html { redirect_to @donor, notice: 'Donor was successfully created.' }
format.json { render json: @donor, status: :created, location: @donor }
else
format.html { render action: "new" }
format.json { render json: @donor.errors, status: :unprocessable_entity }
end
end
else
respond_to do |format|
if @donor.save
format.html { redir开发者_StackOverflowect_to @donor, notice: 'Donor already exists. Please edit donor if needed.'}
format.json { render json: @donor, status: :created, location: @donor }
else
format.html { render action: "new" }
format.json { render json: @donor.errors, status: :unprocessable_entity }
end
end
end
end
Then in my import_tables controller I have this method:
def process_import
@import = ImportTable.find(params[:id])
if @import.import_type == 'Prospects'
#do something here....
elsif @import.import_type == 'Donations'
#do something here...
end
end
I am not sure what exactly I should do in the #do something here...
parts.
I was thinking I should pick out the right columns from @import and put them in [:donor] array and send them to the create method of my donors_controller, but I am not sure exactly how to do that or if that is the right way to go about this.
The missing link is that you need to get to the Class from it's name..
There are several ways to do this, e.g. with an "eval' , but a cleaner and simpler way to do this is to:
# do something:
class_name = @import.import_type
klass = ActiveRecord.const_get(class_name) # now you have a reference to your class
#... then do whatever you like with your symbolic klass, e.g. create your new entry
# klass.find_or_create(...) , klass.find(1), klass.first ,
# klass.create( {attributes for new instance of klass} )
this works so conveniently because in your model you do YourClass < ActiveRecord::Base , your class is part of the ActiveRecord module, Classes in Ruby are constants which are stored in the context in which they are defined (=in their module), therefore you can query that context, e.g. ActiveRecord, and find your class.
If your class was not derived from ActiveRecord::Base , you could still do a:
klass = Kernel.const_get( class_name )
see also: http://infovore.org/archives/2006/08/02/getting-a-class-object-in-ruby-from-a-string-containing-that-classes-name/
if you are going line by line, Keep count of which line you are processing.
then in your #do something areas just call Prospect.new, Donation.new, etc.
validate or save it, and gather up all the errors reported by the object so that you can spit them back to the user with a line number of where the error occured.
You don't need to goto the specific controller methods for each type. Your import logic will basically handle it.
精彩评论