Rails — Id не может быть найден в формах

#ruby-on-rails #ruby-on-rails-3 #forms

#ruby-on-rails #ruby-on-rails-3 #формы

Вопрос:

Есть некоторое время, когда я застрял в этой проблеме. Я пытаюсь передать 3 идентификатора через форму, чтобы сохранить данные в моей базе данных.

 def new
  @person = Person.find(params[:person])
  @honored = Person.find(params[:honored])
  @group = Group.find(params[:group_id])
  @honor = Honor.new
end

def create
  @person = Person.find(current_person)
  @honor = Honor.create(:group => Group.find(params[:group_id]),
           :person => Person.find(params[:person]),
           :honored => Person.find(params[:honored]))
 if @honor.valid?
  flash[:success] = "Honor created."
  redirect_to (:back)
 else
  redirect_to (:back)
 end
end
  

На мой взгляд, где я вызываю new метод:

 <% @asked_groupmembership.each do |agm| %>
<%= link_to "Create Honor", new_honor_path(:group_id => @group.id, :person => current_person.id,
  :honored => agm.member.id) %> 
  

Мои формы:

 <% form_for @honor do |f| %>

 <%= f.hidden_field :group_id, :value => @group.id %>
 <%= f.hidden_field :person, :value => current_person.id %>
 <%= f.hidden_field :honored, :value => @honored.id %>

 <div class="field">
<%= f.label :texto %><br />
<%= f.text_field :texto %>
 </div>
  

Когда я нажимаю кнопку отправки, я получаю эту ошибку:

 Couldn't find Group without an ID

app/controllers/honors_controller.rb:22:in `create'

{"utf8"=>"✓",
 "authenticity_token"=>"C7wofMY4VcyfdS10oc3iglex8nZVBMQ0Nh22nMiaOqs=",
 "honor"=>{"group_id"=>"39",
 "person"=>"2",
 "honored"=>"44",
 ...
                },
 "commit"=>"Insert"}
  

Как я могу это решить?
Спасибо.

##ОТРЕДАКТИРОВАНО##

 class Honor < ActiveRecord::Base
  belongs_to :person, :class_name => 'Person', :foreign_key => "person_id"
  belongs_to :honored, :class_name => 'Person', :foreign_key => "honored_id"
  belongs_to :group, :class_name => 'Group', :foreign_key => "group_id"
  

Ответ №1:

Вам необходимо обновить свой метод create с помощью:

 def create
  @person = Person.find(current_person)
  @honor = Honor.create(:group_id => params[:honor][:group],
           :person_id => params[:honor][:person],
           :honored_id => params[:honor][:honored])
 if @honor.save
 ...
end
  

Потому что после отправки вашей формы вы получили свои данные в params[: honor]. Вы можете увидеть хэш, переданный контроллеру в коде, опубликованном в вашем вопросе:

 "honor"=>{"group"=>"39",
 "person"=>"2",
 "honored"=>"44",
  

Комментарии:

1. изменен ответ… пожалуйста, взгляните.

2. Спасибо, это сработало, были все мои ошибки с именами, извините!. Но то, что я передаю в форме, остается пустым, есть идеи?

3. Я имею в виду, когда я проверяю свою базу данных, у меня есть идентификатор, сохраненный и honor созданный, но все в формах исчезает nil .

4. Если вы выполните в консоли следующий код, вы получите правильную запись в базе данных? Honor.create(:group_id => 3, :person_id => 2, :honored_id => 1)

5. ДА. И я также добавил свои атрибуты, и все это отлично сохранилось.

Ответ №2:

Для того, чтобы сделать его немного более читаемым, давайте сделаем это

Форма:

 <% form_for @honor do |f| %>
  <%= f.hidden_field :group_id, :value => @group.id %>
  <%= f.hidden_field :person_id, :value => current_person.id %>
  <%= f.hidden_field :honored_id, :value => @honored.id %>
  ...
<% end %>
  

Контроллер:

 def new
  @person = Person.find(params[:person])
  @honored = Person.find(params[:honored])
  @group = Group.find(params[:group_id])
  @honor = Honor.new
end

def create
  @person = Person.find(current_person)
  @honor = Honor.create(
    :group => Group.find(params[:honor][:group_id]),
    :person => Person.find(params[:honor][:person_id]),
    :honored => Person.find(params[:honor][:honored_id])
  )

  if @honor.save
    ...
  end
end
  

Каждое скрытое поле внутри формы будет передано контроллеру в качестве параметра внутри params[:honor]

Теперь, взглянув на контроллер, есть кое-что, что выглядит не совсем правильно. create Метод создаст новый экземпляр и сохранит объект, если ошибок нет. Вызов create and then save будет работать, но вы можете либо вызвать new (вместо create ), а затем save , либо просто продолжать использовать create and then valid? . Лично я считаю, что процесс new then save более чистый.

Пример:

 def create
  @person = Person.find(current_person)
  @honor = Honor.new(
    :group => Group.find(params[:honor][:group_id]),
    :person => Person.find(params[:honor][:person_id]),
    :honored => Person.find(params[:honor][:honored_id])
  )

  if @honor.save
    ...
  end
end