2015-12-18 3 views
2

У меня есть модель Rails под названием «Биография», а в биографии есть один образ жизни.Почему это назначение атрибутов вложенных рельсов не работает

class Lifestyle < ActiveRecord::Base 
    belongs_to :biography 
end 

class Biography < ActiveRecord::Base 
    has_one :lifestyle, dependent: :destroy 
    accepts_nested_attributes_for :lifestyle 
end 

И В моей BiographyController Я это:

def update_biography 
    biography = current_user.biography 
    logger.debug("params are: #{params}") 
    logger.debug("biography_params are: #{biography_params}") 
    if biography.update(biography_params) 
    render :json => biography 
    else 
    render :json => { :errors => biography.errors.full_messages }, :status => 400 
    end 
end 

def biography_params 
      params.require(:biography).permit(
             :disability, :hiv_positive, :blood_type, 
             lifestyle_attributes: [:id, :diet, :smoke, :drink]) 
end 

И это то, что я получаю от двух моих заявлений logger.debug выше:

params are: {"lifestyle_attributes"=>{"diet"=>"2", "smoke"=>"false", "drink"=>"2"}, "disability"=>"false", "hiv_positive"=>"false", "blood_type"=>"3", "controller"=>"biographies", "action"=>"update_biography", "id"=>"4", "biography"=>{"disability"=>"false", "hiv_positive"=>"false", "blood_type"=>"3"}} 

biography_params are: {"disability"=>"false", "hiv_positive"=>"false", "blood_type"=>"3"} 

Почему это мои biography_params не содержат атрибуты стиля жизни, хотя я принимаю_nested_attributes_for statment в модели Biography, а также определяю связь между биографией и образом жизни в моделях? Я также добавил атрибуты lifestyle_ в списке разрешений сильных параметров.

Однако, если я запускаю это в рельсах консоли назначение делает работу:

b = Biography.first 
b.update("lifestyle_attributes"=>{"diet"=>"2", "smoke"=>"false", "drink"=>"2"}) 
+2

Ваши параметры должны быть 'params = {" biography "=> {" first_name "=>" new "," last_name "=>" user "," lifestyle_attributes "=> {" diet "=>" 2 "," «smoke» => «false», «drink» => «2»}} ' –

+0

опубликовать форму для –

+0

У меня нет формы для. Я использую обратные ссылки backbone.js и отправляю запрос json. Это заголовок: blood_type: «3» disability: «false» hiv_positive: «false» lifestyle_attributes: {diet: "2", smoke: "false", drink: "2"} – user1801879

ответ

1

Вы можете попробовать

params = {biography: {first_name: "new", last_name: "user", disability: false, hiv_positive: false, blood_type: 3, "lifestyle_attributes: {diet: "2", smoke: "false", drink: "2"}} 

Если вы не хотите biography: на ваших Params вы можете игнорировать require(:biography) на params.require(:biography) до params.permit(...)

Надеюсь, теперь это сработает

Вы получите больше информации о Nested Attributes

+0

Спасибо, сегодня я сделаю снимок. – user1801879

+0

deleing require statement сделал трюк. Удалять ли удаление опасно? В чем его преимущество? Кроме того, он создает новый идентификатор образа для каждого обновления. – user1801879

+0

«Идите к каждому контроллеру, чьи действия запускают массовое присвоение этой модели с помощью параметров» здесь, на этой модели, поэтому вы указываете, какая модель ... вы игнорируете требуемую модель, а не только проблему. –

2

require и permit фактически метод ActionController::Parameters. require, который в этом случае является :biography, должен присутствовать в хэше, который вы отправляете с вашего основного вида.

Метод require обеспечивает наличие определенного параметра, и если он не указан, метод require вызывает ошибку. Он возвращает экземпляр ActionController::Parameters для ключа, переданного в запрос i.e :biography.

+0

То, что вы говорите, имеет смысл. Но почему все работает, если я удаляю атрибуты lifestyle из разрешения. если вы видите, что оператор logger «params is:», в конце его есть «: biography =>», даже если я не отправляю его в хеш, сгенерированный из представлений огород. – user1801879

1

Проблема в том, что lifestyle_attributes не являются частью хэша параметров biography. Вы должны иметь:

params: { 
    biography: { 
     lifestyle_attributes: { 
     ... 
     } 
    } 
} 

Это позволит метод PARAMS для доступа к данным должным образом.

Чтобы объяснить, как это работает, вы должны смотреть на то, как работает ActionController::Parameters класс:

Возвращает новый ActionController::Parameters экземпляр, который включает в себя только данные фильтры и устанавливает допустимый атрибут для объекта действительности.

Каждый раз, когда вы используете params.require(:x).permit(:y), он возвращает новый хэш с только разрешенных Params. Эти разрешенные параметры должны быть вложены в нужный параметр.

Как вы продемонстрировали, это хорошо работает ...

biography_params являются: {"disability"=>"false", "hiv_positive"=>"false", "blood_type"=>"3"}

Проблема заключается в том, что, поскольку lifestyle_attributes является не вложен в biography, его параметры не возвращаются после вызова метода Params.


Чтобы исправить это будет в вашей форме:

#app/views/biographies/new.html.erb 
<%= form_for @biography do |f| %> 
    <%= ... biography attributes %> 
    <%= f.fields_for :lifestyle do |l| %> 
     <%= lifestyle fields %> 
    <% end %> 
    <%= f.submit %> 
<% end %> 

Я не знаю, как вы сделали это в настоящее время, но так или иначе, вы прикреплены lifestyle атрибуты за пределами biography хэш.

Смежные вопросы