Hi, I have a problem creating an new instance of an object using params posted from a form. The object being created is not a sub class of ActiveRecord and is very simple. It''s model file is just: class Search attr_accessor :major_build_id, :minor_build_id, :environment_id, :system_id end The controller creates an empty instance variable the first time the page is called, else it tries to populate it with the values of params from the form. class ResultsController < ApplicationController def index list render :action => ''list'' end def list if request.get? @search = Search.new else @search = Search.new(params[:search]) end end end The form on the results/index page which populates the form posts back to itself and is also very simple <%= start_form_tag %> <div>Major Build Name<%= select :search, :major_build_id, [["Select", ""]]+@major_builds %></div> <div>Minor Build Name<%= select :search, :minor_build_id, [["Select", ""]]+@minor_builds %></div> <div>Environment<%= select :search, :environment_id, [["Select", ""]]+@environments %></div> <div>System<%= select :search, :system_id, [["Select", ""]]+@systems %></div> <div><%= submit_tag ''Update Results'' %></div> <%= end_form_tag %> The first time I call the page (using the GET request) is fine, but if I use the form to post any data I get an error. ArgumentError in Results#index wrong number of arguments (1 for 0) RAILS_ROOT: ./script/../config/.. Application Trace <#> | Framework Trace <#> | Full Trace <#> #{RAILS_ROOT}/app/controllers/results_controller.rb:13:in `initialize'' #{RAILS_ROOT}/app/controllers/results_controller.rb:13:in `new'' #{RAILS_ROOT}/app/controllers/results_controller.rb:13:in `list'' #{RAILS_ROOT}/app/controllers/results_controller.rb:4:in `index'' -e:3:in `load'' -e:3 c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/base.rb:853:in `send'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/base.rb:853:in `perform_action_without_filters'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/filters.rb:332:in `perform_action_without_benchmark'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/benchmarking.rb:69:in `perform_action_without_rescue'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/benchmarking.rb:69:in `measure'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/benchmarking.rb:69:in `perform_action_without_rescue'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/rescue.rb:82:in `perform_action'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/base.rb:369:in `send'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/base.rb:369:in `process_without_session_management_support'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/session_management.rb:116:in `process'' c:/ruby/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/dispatcher.rb:38:in `dispatch'' c:/ruby/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/webrick_server.rb:117:in `handle_dispatch'' c:/ruby/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/webrick_server.rb:83:in `service'' c:/ruby/lib/ruby/1.8/webrick/httpserver.rb:104:in `service'' c:/ruby/lib/ruby/1.8/webrick/httpserver.rb:65:in `run'' c:/ruby/lib/ruby/1.8/webrick/server.rb:155:in `start_thread'' c:/ruby/lib/ruby/1.8/webrick/server.rb:144:in `start'' c:/ruby/lib/ruby/1.8/webrick/server.rb:144:in `start_thread'' c:/ruby/lib/ruby/1.8/webrick/server.rb:94:in `start'' c:/ruby/lib/ruby/1.8/webrick/server.rb:89:in `each'' c:/ruby/lib/ruby/1.8/webrick/server.rb:89:in `start'' c:/ruby/lib/ruby/1.8/webrick/server.rb:79:in `start'' c:/ruby/lib/ruby/1.8/webrick/server.rb:79:in `start'' c:/ruby/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/webrick_server.rb:69:in `dispatch'' c:/ruby/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/servers/webrick.rb:59 c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:18:in `require__'' c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:18:in `require'' c:/ruby/lib/ruby/gems/1.8/gems/activesupport-1.2.5/lib/active_support/dependencies.rb:214:in `require'' c:/ruby/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/server.rb:28 c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:18:in `require__'' c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:18:in `require'' c:/ruby/lib/ruby/gems/1.8/gems/activesupport-1.2.5/lib/active_support/dependencies.rb:214:in `require'' ./script/server:3 #{RAILS_ROOT}/app/controllers/results_controller.rb:13:in `initialize'' #{RAILS_ROOT}/app/controllers/results_controller.rb:13:in `new'' #{RAILS_ROOT}/app/controllers/results_controller.rb:13:in `list'' #{RAILS_ROOT}/app/controllers/results_controller.rb:4:in `index'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/base.rb:853:in `send'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/base.rb:853:in `perform_action_without_filters'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/filters.rb:332:in `perform_action_without_benchmark'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/benchmarking.rb:69:in `perform_action_without_rescue'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/benchmarking.rb:69:in `measure'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/benchmarking.rb:69:in `perform_action_without_rescue'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/rescue.rb:82:in `perform_action'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/base.rb:369:in `send'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/base.rb:369:in `process_without_session_management_support'' c:/ruby/lib/ruby/gems/1.8/gems/actionpack-1.11.2/lib/action_controller/session_management.rb:116:in `process'' c:/ruby/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/dispatcher.rb:38:in `dispatch'' c:/ruby/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/webrick_server.rb:117:in `handle_dispatch'' c:/ruby/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/webrick_server.rb:83:in `service'' c:/ruby/lib/ruby/1.8/webrick/httpserver.rb:104:in `service'' c:/ruby/lib/ruby/1.8/webrick/httpserver.rb:65:in `run'' c:/ruby/lib/ruby/1.8/webrick/server.rb:155:in `start_thread'' c:/ruby/lib/ruby/1.8/webrick/server.rb:144:in `start'' c:/ruby/lib/ruby/1.8/webrick/server.rb:144:in `start_thread'' c:/ruby/lib/ruby/1.8/webrick/server.rb:94:in `start'' c:/ruby/lib/ruby/1.8/webrick/server.rb:89:in `each'' c:/ruby/lib/ruby/1.8/webrick/server.rb:89:in `start'' c:/ruby/lib/ruby/1.8/webrick/server.rb:79:in `start'' c:/ruby/lib/ruby/1.8/webrick/server.rb:79:in `start'' c:/ruby/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/webrick_server.rb:69:in `dispatch'' c:/ruby/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/servers/webrick.rb:59 c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:18:in `require__'' c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:18:in `require'' c:/ruby/lib/ruby/gems/1.8/gems/activesupport-1.2.5/lib/active_support/dependencies.rb:214:in `require'' c:/ruby/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/server.rb:28 c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:18:in `require__'' c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:18:in `require'' c:/ruby/lib/ruby/gems/1.8/gems/activesupport-1.2.5/lib/active_support/dependencies.rb:214:in `require'' ./script/server:3 -e:3:in `load'' -e:3 Request *Parameters*: {"search"=>{"minor_build_id"=>"", "major_build_id"=>"", "system_id"=>"1", "environment_id"=>""}, "commit"=>"Update Results"} However I''ve found that if I update the "list" action in the results controller to this longer and uglier version, it works. def list @search = Search.new if request.post? @search.major_build_id = params[:search]["major_build_id"].to_i() @search.minor_build_id = params[:search]["minor_build_id"].to_i() @search.environment_id = params[:search]["environment_id"].to_i() @search.system_id = params[:search]["system_id"].to_i() end end This seems a bit long winded and I''m sure there is a simpler and more elegant way. Is there something I''m missing? thanks Iain -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060211/b3c00f92/attachment-0001.html
dblack@wobblini.net
2006-Feb-11 01:46 UTC
[Rails] Creating new object using params posted from form
Hi -- On Fri, 10 Feb 2006, Iain Rose wrote:> Hi, > > I have a problem creating an new instance of an object using params posted > from a form. > > The object being created is not a sub class of ActiveRecord and is very > simple. It''s model file is just: > > > class Search > > attr_accessor :major_build_id, :minor_build_id, :environment_id, > :system_id > > end > > > The controller creates an empty instance variable the first time the page is > called, else it tries to populate it with the values of params from the > form. > > > class ResultsController < ApplicationController > > def index > list > render :action => ''list'' > end > > def list > if request.get? > @search = Search.new > else > @search = Search.new(params[:search])What you''ve done is equivalent to: class C end c = C.new("arg") # wrong # of arguments: 1 for 0 You''d need to write an initialize method -- for example class C def initialize(*x) # optional argument x # do whatever here end end Similarly, in your Search class, you would need to define initialize, probably to handle an optional argument (since it looks like you want to be able to call it with or without).> *Parameters*: {"search"=>{"minor_build_id"=>"", "major_build_id"=>"", > "system_id"=>"1", "environment_id"=>""}, "commit"=>"Update Results"} > > However I''ve found that if I update the "list" action in the results > controller to this longer and uglier version, it works. > > def list > @search = Search.new > if request.post? > @search.major_build_id = params[:search]["major_build_id"].to_i() > @search.minor_build_id = params[:search]["minor_build_id"].to_i() > @search.environment_id = params[:search]["environment_id"].to_i() > @search.system_id = params[:search]["system_id"].to_i() > end > end > > This seems a bit long winded and I''m sure there is a simpler and more > elegant way. Is there something I''m missing?If you do something like this in the Search class: class Search attr_accessor :major_build_id, :minor_build_id, :environment_id, :system_id def initialize(*search_hash) if search_hash search_hash.each do |key,value| send("#{key}=", value) # This calls the appropriate # writer method, matching the key end end end end then you could do: @search = Search.new(params[:search]) and/or @search = Search.new in the controller, depending on conditions, etc. (It seems a bit anomalous to have this Search class among the models, but that''s another matter :-) David -- David A. Black (dblack@wobblini.net) Ruby Power and Light (http://www.rubypowerandlight.com) "Ruby for Rails" chapters now available from Manning Early Access Program! http://www.manning.com/books/black
Thanks for the advice. Can I ask why you don''t need to do this when using models that exist in the db. For example, when I use the scaffold generator to create a model called Search in a controller called Results, I get this in the controller .... class ResultsController < ApplicationController ............... def create @search = Search.new(params[:search]) if @search.save flash[:notice] = ''Search was successfully created.'' redirect_to :action => ''list'' else render :action => ''new'' end end I''m not intending to use scaffolding throughout my app but it proves it can work out of the box (sometimes). The class definition of the Search model doesn''t have an initialize method. Does it just inherit something simliar to your suggestion from it''s super class? Also, as this is my first attempt at a Rails app (I''m branching out on my own after working through the agile book), can you explain what you mean by ... It seems a bit anomalous to have this Search class among the models I''d like to start on the right tracks and not get into bad habits. Thanks again for the advice. Iain On 10/02/06, dblack@wobblini.net <dblack@wobblini.net> wrote:> > Hi -- > > On Fri, 10 Feb 2006, Iain Rose wrote: > > > Hi, > > > > I have a problem creating an new instance of an object using params > posted > > from a form. > > > > The object being created is not a sub class of ActiveRecord and is very > > simple. It''s model file is just: > > > > > > class Search > > > > attr_accessor :major_build_id, :minor_build_id, :environment_id, > > :system_id > > > > end > > > > > > The controller creates an empty instance variable the first time the > page is > > called, else it tries to populate it with the values of params from the > > form. > > > > > > class ResultsController < ApplicationController > > > > def index > > list > > render :action => ''list'' > > end > > > > def list > > if request.get? > > @search = Search.new > > else > > @search = Search.new(params[:search]) > > What you''ve done is equivalent to: > > class C > end > > c = C.new("arg") # wrong # of arguments: 1 for 0 > > You''d need to write an initialize method -- for example > > class C > def initialize(*x) # optional argument x > # do whatever here > end > end > > Similarly, in your Search class, you would need to define initialize, > probably to handle an optional argument (since it looks like you want > to be able to call it with or without). > > > *Parameters*: {"search"=>{"minor_build_id"=>"", "major_build_id"=>"", > > "system_id"=>"1", "environment_id"=>""}, "commit"=>"Update Results"} > > > > However I''ve found that if I update the "list" action in the results > > controller to this longer and uglier version, it works. > > > > def list > > @search = Search.new > > if request.post? > > @search.major_build_id = params[:search]["major_build_id"].to_i() > > @search.minor_build_id = params[:search]["minor_build_id"].to_i() > > @search.environment_id = params[:search]["environment_id"].to_i() > > @search.system_id = params[:search]["system_id"].to_i() > > end > > end > > > > This seems a bit long winded and I''m sure there is a simpler and more > > elegant way. Is there something I''m missing? > > If you do something like this in the Search class: > > class Search > attr_accessor :major_build_id, :minor_build_id, > :environment_id, :system_id > > def initialize(*search_hash) > if search_hash > search_hash.each do |key,value| > send("#{key}=", value) # This calls the appropriate > # writer method, matching the key > end > end > end > end > > then you could do: > > @search = Search.new(params[:search]) > > and/or > > @search = Search.new > > in the controller, depending on conditions, etc. > > (It seems a bit anomalous to have this Search class among the models, > but that''s another matter :-) > > > David > > -- > David A. Black (dblack@wobblini.net) > Ruby Power and Light (http://www.rubypowerandlight.com) > > "Ruby for Rails" chapters now available > from Manning Early Access Program! http://www.manning.com/books/black > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060211/b9e33b5e/attachment.html
Pete Yandell
2006-Feb-11 21:32 UTC
[Rails] Creating new object using params posted from form
David is right. The scaffolding code is like that because it expects Search to be an ActiveRecord subclass. It''s ActiveRecord that provides the ability to call new with a hash. If you''re not subclassing ActiveRecord, you need to implement that yourself. Cheers, Pete Yandell