2011-01-17 9 views
9

Ho il seguente codice nel mio modulo.errore multiparametro con datetime_select

<%= f.datetime_select(:date_time, :prompt => {:day => 'Day', :month => 'Month', :year => 'Year'}, :start_year => Date.today.year, :end_year => Date.today.year + 2, :minute_step => 15, :include_blank => false) %> if either one is blank. 

Quando uno dei campi viene lasciato vuoto, ottengo:

1 error(s) on assignment of multiparameter attributes 

Le params che vengono passati sono:

{"utf8"=>"✓", 
"authenticity_token"=>"kQpfsj5RxnDtxkvBdwPEFnX1fY6euKnMQeDRAkvJvIE=", 
"event"=>{"description"=>"", 
"venue"=>"", 
"street"=>"", 
"city"=>"", 
"country_id"=>"", 
"date_time(1i)"=>"", 
"date_time(2i)"=>"", 
"date_time(3i)"=>"", 
"date_time(4i)"=>"00", 
"date_time(5i)"=>"00", 
"ticket_url"=>""}, 
"x"=>"94", 
"y"=>"12"} 

Chiunque sa perché questo sta accadendo?

Sembra esserci una correzione "sporca" per questo in questo link, ma forse c'è una soluzione migliore in Rails 3?

+0

Is il tuo campo data_time virtuale (nessuna colonna db effettiva)? Se la risposta di gabeodess è ciò che stai cercando. – tybro0103

risposta

4

cristiana. Questo è un bug in Rails che controlla il database per dedurre il tipo necessario per gli attributi multiparametrici. La mia ipotesi è che il tuo attributo "date_time" non sia associato a una colonna temporale nel tuo database.

recente ho affrontato questo problema dove volevo un attributo non database per attributi multiparametrici accettati, questa era la soluzione migliore che ho potuto venire con:

mi sono trovato a voler impostare un attr_accessor per gestire passando una data al mio modello in un tag form_for con l'helper f.datetime_select. Quindi questo è quello che avevo:

Modello:

attr_accessor :my_time 

Vista:

<%= f.datetime_select :my_time %> 

Purtroppo quando presento la mia forma ottengo questo:

1 error(s) on assignment of multiparameter attributes 

Ebbene si scopre che questo è in realtà un bug di Rails per cui è stato inviato un ticket. Nel frattempo come facciamo a fare questo lavoro? L'unica soluzione che ho trovato che era lontanamente attraente era quella di utilizzare composed_of in sostituzione di attr_accessor. così ...

Modello:

composed_of :my_time, 
       :class_name => 'Time', 
       :mapping => %w(Time to_s), 
       :constructor => Proc.new{ |item| item }, 
       :converter => Proc.new{ |item| item } 

ne so quasi nulla sul metodo composed_of in modo probabilmente si dovrebbe fare la propria lettura su di esso, ma quello che so è che crea sia un lettore e scrittore per la variabile di istanza data e, cosa più importante, il setter accetta attributi multiparametro. Come ho scelto le opzioni:

class_name: il nome della nostra classe prevista. In questo caso, Time
mapping: il primo argomento è la classe e il secondo argomento sembra funzionare con qualsiasi metodo a cui un'istanza della classe risponde. Ho scelto il costruttore to_s : Non sono proprio sicuro di come dovrebbe funzionare. Sembra essere chiamato quando @my_time è nil.Convertitore
: Non proprio sicuro di come dovrebbe funzionare. Sembra essere chiamato quando da my_time =, ma non sembra essere applicato con l'assegnazione di massa. Un problema che ho riscontrato con questa soluzione era che i tempi venivano impostati in UTC invece del fuso orario dell'ambiente. Così, purtroppo, non possiamo usare my_time direttamente, ma invece bisogno di convertirlo al corretto fuso orario:

Time.zone.parse(my_time.to_s(:number)) 
+0

Yippie! Mi hai appena salvato un giorno intero :) Bel trucco – tybro0103

+0

Questo sembra essere ancora un problema, @gabeodess. Ti capita di conoscere il numero del biglietto in Rails per questo problema? –

+0

Downgoted, perché il collegamento con la soluzione è offline. – iblue

-1

Rimuovi :include_blank => false dal codice.

<%= f.datetime_select(:date_time, :prompt => {:day => 'Day', :month => 'Month', :year => 'Year'}, :start_year => Date.today.year, :end_year => Date.today.year + 2, :minute_step => 15 %> 

Grazie ....

+0

Continua a ricevere lo stesso errore. Ora ho: <% = f.datetime_select (: date_time,: prompt => {: day => 'Day',: month => 'Month',: year => 'Year'},: start_year => Date. today.year,: end_year => Date.today.year + 2,: minute_step => 15)%> –

-5

stavo affrontando lo stesso problema. Ho appena aggiunto attr_accessible per quell'attributo e funziona perfettamente.

Spero che aiuti.

0

Ho avuto lo stesso problema utilizzando un elenco a discesa di data che non era supportato da un attributo di database. Ho scritto un po 'di middleware rack per far fronte al problema:

class DateParamsParser 
    def initialize(app) 
    @app = app 
    end 

    def call(env) 
    if %w{POST PUT}.include? env['REQUEST_METHOD'] 
     params = Rack::Utils.parse_query(env["rack.input"].read, "&") 

     # selects only relevant params like 'date1(1i)' 
     filtered_params = params.select{ |key, value| key =~ /\(\di\)/ } 
     # delete date params 
     filtered_params.each { |key, value| params.delete(key) } 

     # returns something like {'date1' => [2012, 5, 14], 'date2' => [2002, 3, 28]} 
     date_array_params = filtered_params.sort.reduce({}) do |array_params, keyvalue| 
     date_key = keyvalue.first.match(/(.+)\(/)[1] + ']' 
     array_params[date_key] ||= [] 
     array_params[date_key] << keyvalue.last 
     array_params 
     end 

     # Creates params with date strings like {'date1' => '2012-5-14', 'date2' => '2002-3-28'} 
     date_params = Hash[date_array_params.map{ |key, date_array| [key, date_array.join('-')] }] 

     params.merge! date_params 
     env["rack.input"] = StringIO.new(Rack::Utils.build_query(params)) 
     env["rack.input"].rewind 
    end 

    @app.call(env) 
    end 
end 

E in application.rb ho messo

config.middleware.insert_before ActionDispatch::ParamsParser, "DateParamsParser" 

Nota che ho solo costruire una stringa di data qui. Pertanto, se si richiede anche del tempo, è necessario creare lo date_params in modo diverso.

1

What Does ActiveRecord::MultiparameterAssignmentErrors Mean?

def initialize(attributes={}) 
    date_hack(attributes, "deliver_date") 
    super(attributes) 
end 

def date_hack(attributes, property) 
    keys, values = [], [] 
    attributes.each_key {|k| keys << k if k =~ /#{property}/ }.sort 
    keys.each { |k| values << attributes[k]; attributes.delete(k); } 
    attributes[property] = values.join("-") 
end 
0

ho affrontato lo stesso problema con il modello sotto

class Reservation < ActiveRecord::Base 
    attr_accessor :sid, :check_in, :credit_card_number, :expiration_date 
    attr_accessible :expiration_date 
end 

La forma corrispondente con il campo per la data di scadenza:

<div class="field"> 
    <%= f.label :expiration_date %> 
    <%= f.date_select(:expiration_date, start_year: Time.now.year + 3, :end_year => Time.now.year - 3, discard_day: true) %> 
</div> 

come detto da @ gabeodess il problema è controllare il database per dedurre il tipo di conseguenza il s Olution ho fatto per essa stava aggiungendo il seguente codice al modello di mettere il tipo di attributo necessario in questo caso: expiration_date modo che il modello viene modificato per essere la seguente

class Reservation < ActiveRecord::Base 
    attr_accessor :sid, :check_in, :credit_card_number, :expiration_date 
    attr_accessible :expiration_date 
    columns_hash["expiration_date"] = ActiveRecord::ConnectionAdapters::Column.new("expiration_date", nil, "date") 
end 

Spero che questo è utile

+0

ActiveRecord :: ConnectionAdapters :: Column.new funziona ma uccide la capacità di fare db: schema: caricare per me – rnaud