0

我有一个像这样的隐藏形式:

= 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'

其中一些属性是序列化数组,但 padrino 似乎不是从字符串解析数组,因此当我尝试从存储在 params 中的这个 attr 哈希中保存记录时,db 会引发序列化错误:

{"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\"]"}

我可以用这段丑陋的代码来解析数组字符串:

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

但这似乎很愚蠢,sinatra 应该自动解析它(或者不是?),或者我可能以错误的方式生成表单。我该如何解决这种行为?

注意:刚刚尝试生成这样的表单:

- 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)
4

2 回答 2

1

我的建议是避免以数组和散列的形式发送数据。您尝试发送的数据可以很容易地作为一个字符串发送,然后在另一侧拆分。例如,为什么不将演员以逗号分隔的字符串形式发送,然后param["cast_members"].split(/\s*,\s*/)在收到时发送?某种自动提示将是谨慎的,否则您最终会得到很多拼写错误的名称。这将通过在发送数据之前用 slug 替换条目来帮助您进一步分隔数据。看看 StackOverflow 做标记字段的方式。

如果您确实需要作为数组发送,请考虑将其转换为 JSON,然后在另一端发送和反序列化,而不是自己做。

于 2013-02-25T16:00:23.863 回答
0

我想尽可能地保持 LOC 和可读性,因此使用 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
于 2013-02-25T19:50:38.047 回答