0

I have a hidden form like this:

= form_for movie, 'create', method: 'POST' do |f|
  - Movie.attribute_names.each do |attr|
   = f.hidden_field attr.to_sym, value: movie.send(attr)
  = f.submit 'Save this Movie', class: 'button'

Some of this attributes are serialized arrays, but padrino seems not to be parsing arrays from strings, so the db raises serialization error when I try to save a record from this attr hash stored in params:

{"title"=>"Iron Man 2",
 "directors"=>"[\"Jon Favreau\"]",
 "cast_members"=>"[\"Robert Downey Jr.\", \"Gwyneth Paltrow\", \"Don Cheadle\", \"Scarlett Johansson\", \"Sam Rockwell\"]",
 "genres"=>"[\"Action\", \"Adventure\", \"Sci-Fi\"]",
 "length"=>"124",
 "trailer_url"=>"http://imdb.com/video/screenplay/vi1172179225/",
 "year"=>"2010",
 "languages"=>"[\"English\", \"French\", \"Russian\"]"}

I can parse the array string with this ugly chunk of code:

Movie.serialized_attributes.keys.each do |k|
  movie[k] = movie[k].gsub(/\"|\[|\]/, '').split(', ') if movie[k]
end

but that seems just stupid, sinatra should be parsing it automatically (or not?), or maybe I'm generating the form the wrong way. How can I fix this behavior?

Note: just tried generating the form like this:

- Movie.attribute_names.each do |attr|
   - if Movie.serialized_attributes.keys.include? attr
     = f.hidden_field attr.to_sym, value: movie.send(attr), multiple: true
   - else
     = f.hidden_field attr.to_sym, value: movie.send(attr)
ichigolas
  • 7,595
  • 27
  • 50

2 Answers2

1

My advice would be to steer well clear of sending data in the form of arrays and hashes. The data you're trying to send could just as easily be sent as one string and then split on the other side. For instance, why not send the cast members as a comma delimited string and then param["cast_members"].split(/\s*,\s*/) on receipt? Some kind of autosuggest would be prudent or you'll end up with lots of misspelt names. This will help you delimit the data further by replacing entries with slugs before the data is sent. Look at the way StackOverflow does the tagging field.

If you really need to send as an array, consider converting it to JSON and then sending it and deserializing on the other end instead of doing it yourself.

ian
  • 12,003
  • 9
  • 51
  • 107
  • I was hoping there was some helpers so passing array objects as input values would automatically generate the right hidden inputs. Worked around it with ajax. – ichigolas Feb 25 '13 at 19:46
0

I wanted to maintain LOC and readability at best possible level, so worked around it with AJAX:

= link_to 'Save this movie', class: 'button', id: "create_movie_#{movie_id}"
- content_for :scripts do
  :javascript
    $(function(){
      $('#create_movie_#{movie_id}').on('click', function(){
        $.post("/movies/create.json",
        {movie: #{movie.to_json}},
        function(r){
          console.log('Response arrived:')
          console.log(r)
        })
      })
    })

# controller.rb
post :create, provides: [:html, :json] do
  case content_type
  when :json
    Movie.create(params[:movie]).to_json
  when :html
    if @movie = Movie.create(params[:movie])
      render 'movies/show'
    else
      redirect 'movies/fetch', error: 'Something went wrong'
    end
  end
end
ichigolas
  • 7,595
  • 27
  • 50