Создайте несколько записей с флажком и сильными параметрами в Rails4

У меня проблемы со следующим сценарием:

Мои пользователи выполняют поиск по ключевым словам, который создает список. У пользователя есть 2 действия: либо добавить их в таблицу избранного, либо заблокировать их с помощью флажков.

Моя проблема заключается в том, что когда пользователи нажимают «Добавить в избранное», форма передает список хэшей моему сильному методу params, и я не могу передать его правильно.

Я думаю, проблема в том, что хеш, требуемый strong_params, находится внутри другого хеша.

Также я понятия не имею, как передать тот же хеш в BlockController, когда пользователь нажимает «Блокировать».

Это сообщение об ошибке:

param is missing or the value is empty: {:favorites=>{:name=>"Jon Doe", :title=>"Provider", :company=>"Acme", :location=>"Dubai", :profile=>"Group A", :notes=>""}}

Мои результаты.html.erb

<table class="table table-striped table-bordered">
  <tr>
      <th class="center">Name</th>
      <th class="center">Title</th>
      <th class="center">Company</th>
      <th class="center">Location</th>
      <th class="center">Profile</th>
      <th class="center">Select</th>

  </tr>
  <%= form_tag favorites_path do %>
        <%= @results.length %>
        <% @results.each do |key,value| %>

            <tr>
              <td><%= value['name'] %></td>
              <td><%= value['title'] %></td>
              <td><%= value['company'] %></td>
              <td><%= value['location'] %></td>
              <td><%= link_to 'Profile', value['profile'],:target => "_blank"%></td>
              <td><%=check_box_tag 'favorite[]',  {:name => value['name'],:title =>value['title'],:company => value['company'],:location => value['location'], :profile=> value['profile'], :notes =>""}%></td>

        </tr>

        <% end %>
    <%= submit_tag "Add to Favorites", name: 'add', class: 'btn btn-primary' %>
    <%= submit_tag "Block Profiles", name: 'block', class: 'btn btn-danger' %>
  <% end %>
</table>

вот как выглядит мой метод strong_params:

def favorite_params

  params[:profiles].each do |e|
    params.require(e).permit(:name, :title, :company, :location, :profile, :notes)
  end
end

Любые идеи?

Обновление:

Я могу передать параметры как:

def favorite_params
      params.permit(:commit,favorite:[])
    end

создать метод:

def create
    @favorite = Favorite.new(favorite_params)
    @favorite.user_id = current_user.id
    respond_to do |format|
      if @favorite.save
        format.html { redirect_to @favorite, notice: 'Favorite was successfully created.' }
        format.json { render :show, status: :created, location: @favorite }
        format.js { render :show, status: :created, location: @favorite }

      else
        format.html { render :new }
        format.json { render json: @favorite.errors, status: :unprocessable_entity }

      end
    end
 end

person Altons    schedule 13.08.2014    source источник
comment
Предлагаем вам сохранить исходную версию сценариев просмотра и переместить новые сценарии просмотра в раздел Обновление.   -  person Jaugar Chang    schedule 15.08.2014


Ответы (2)


Ссылка на http://api.rubyonrails.org/classes/ActionController/Parameters.html Не используйте each, используйте Permit или Request напрямую. Попробуйте следующее:

params.permit(profiles: {favorites: [:name, :title, :company, :location, :profile, :notes]})
#or :
params.permit(profiles: [{favorites: [:name, :title, :company, :location, :profile, :notes]}])
#=>{:profiles=>{:favorites=>{:name=>"Jon Doe", :title=>"Provider", :company=>"Acme", :location=>"Dubai", :profile=>"Group A", :notes=>""}}}

or :

params.require(:profiles).permit( favorites: [:name, :title, :company, :location, :profile, :notes])
#=>{:favorites=>{:name=>"Jon Doe", :title=>"Provider", :company=>"Acme", :location=>"Dubai", :profile=>"Group A", :notes=>""}}

ОБНОВЛЕНИЕ

Согласно модификации представления OP, favorite_params должно быть:

params.require(:favorite)

Затем в действии создания используйте each для создания каждого члена массива, поскольку check_box передает строку как значение, нам нужно снова преобразовать строку в хэш.

favorite_params.each do |fp|
  f=Favorite.new(eval(fp))
  f.user_id = current_user.id
  f.save
end

Но использовать eval для передачи параметров небезопасно. Я предлагаю вам изменить свое представление на:

<%= form_tag favorites_path do %>
  <%= @results.length %>
  <% @results.each do |key,value| %>
    <tr>
      <td><%= value['name'] %></td>
      <td><%= value['title'] %></td>
      <td><%= value['company'] %></td>
      <td><%= value['location'] %></td>
      <td><%= link_to 'Profile', value['profile'],:target => "_blank"%></td>
      <td><%= check_box_tag "favorites[#{value['name']}][checked]", 'checked',true %>
          <%= hidden_field_tag "favorites[#{value['name']}][name]" , value['name'] %>
          <%= hidden_field_tag "favorites[#{value['name']}][title]" , value['title'] %>
          <%= hidden_field_tag "favorites[#{value['name']}][company]" , value['company'] %>
          <%= hidden_field_tag "favorites[#{value['name']}][location]" , value['location'] %>
          <%= hidden_field_tag "favorites[#{value['name']}][profile]" , value['profile'] %>
          <%= hidden_field_tag "favorites[#{value['name']}][note]" , "" %>
      </td>
    </tr>
  <% end %>
  <%= submit_tag "Add to Favorites", name: 'add', class: 'btn btn-primary' %>
  <%= submit_tag "Block Profiles", name: 'block', class: 'btn btn-danger' %>
<% end %>

С этого представления у вас могут быть такие параметры:

{:favorites=>{
  "Jon Doe" => {:checked => "checked", :name=>"Jon Doe", :title=>"Provider", :company=>"Acme", :location=>"Dubai", :profile=>"Group A", :notes=>""},
  "Alberto" => {:name=>"Alberto", :title=>"DS", :company=>"Dufrain", :location=>"chester", :profile=>"", :notes=>""}
  }
}

Затем измените свой favorite_params на:

params.require(:favorites).select{|k,v| v[:checked]}.map{|k,v| v.except(:checked)}

Используйте select, чтобы получить все отмеченные элементы, кроме хэш-ключа checked, сгенерированного check_box, чтобы вы могли получить массив хэшей, например:

[{"name"=>"Jon Doe", "title"=>"Provider", "company"=>"Acme", "location"=>"Dubai", "profile"=>"Group A", "notes"=>""}]

Тогда вы можете безопасно использовать favorite_params без eval.

Но, на мой взгляд, ваш запрос так похож на вопрос Mark V. . Таким образом, вы можете учиться использовать accepts_nested_attributes_for для упрощения своего кода.

person Jaugar Chang    schedule 13.08.2014
comment
спасибо, но не работает - передает strong_params, но вылетает в def create с этой ошибкой ```{profiles=›[]} Недопустимые параметры: utf8, authentication_token, add``` - person Altons; 13.08.2014
comment
Можете ли вы опубликовать код вашего метода создания. Я обновил свой ответ, чтобы показать результаты, которые возвращаются strong_params, требуют и разрешают возврат по-разному, что может вызвать ошибку метода создания. - person Jaugar Chang; 14.08.2014
comment
Я могу передавать параметры с помощью params.permit(:commit,favorite:[]), но не знаю, как create будет обрабатывать несколько записей одновременно. Я немного изменил форму, чтобы упростить передачу данных - person Altons; 14.08.2014
comment
Можете ли вы поместить @favorite в действие создания и посмотреть, что произошло? - person Jaugar Chang; 14.08.2014
comment
Favorite_params имеет следующие значения:{"commit"=>"Add to Favorites", "favorite"=>["{:name=>\"Alberto\", :title=>\"DS\", :company=>\"Dufrain\", :location=>\"chester\", :profile=>\"\", :notes=>\"\"}", "{:name=>\"Eduardo\", :title=>\"DS\", :company=>\"Dufrain\", :location=>\"chester\", :profile=>\"\", :notes=>\"\"}"]} - person Altons; 14.08.2014

Я иду домой, поэтому мне нужно использовать свой телефон, чтобы ввести новый ответ. мое заклинание может ошибаться.

как вы видите в своей консоли. вы должны использовать только массив избранного.

params.require(:favorite)

затем в вашем действии создания используйте каждый для создания каждого члена массива.

favorite_params.each do |fp|
  f=Favorite.new(fp)
  f.user_id =
  f.save
end
person Jaugar Chang    schedule 14.08.2014
comment
Где-то там! fp — это строка, которую необходимо использовать с помощью eval(fp) для обратного преобразования в хэш. Не могли бы вы обновить свой ответ с помощью eval(), чтобы я мог отметить его как решение? Большое спасибо за вашу помощь - person Altons; 14.08.2014
comment
Этот ответ я разместил с другой временной учетной записью на своем телефоне, поэтому я могу удалить его позже. И я обновил свой первоначальный ответ и дал вам больше советов. Вы знаете, по какой-то причине страница входа SO не работает в Китае, мне приходится использовать разные учетные записи на разных устройствах. Извините за путаницу двух ответов. - person Jaugar Chang; 15.08.2014