Rails 3: виртуальный атрибут не установлен

У меня есть следующая модель User с виртуальным атрибутом artist_attributes:

class User < ActiveRecord::Base
  attr_accessor :artist_attributes
  attr_accessible :artist_attributes

  belongs_to :artist
  accepts_nested_attributes_for :artist, update_only: true
end

Вот модель художника:

class Artist < ActiveRecord::Base
  has_one :user
end

Проблема в том, что виртуальный атрибут не устанавливается. Например, вот мой пользовательский контроллер:

class Members::UsersController < Members::BaseController
  def update
    current_user.artist_attributes = params[:user].delete(:artist_attributes)
    p current_user.artist_attributes # => nil
    # ...
  end
end

И вот форма, которая отправляется:

<%= simple_form_for current_user, url: members_profile_path do |f| %>
  <%= f.simple_fields_for :artist do |ff| %>
    <%# ... %>
  <% end %>

  <%= f.submit "Edit profile", class: "btn btn-primary", disable_with: "Editing profile..." %>
<% end %>

Почему не устанавливается виртуальный атрибут artist_attributes? Это из-за вложенной формы?

Update

Вот хэш параметров после отправки формы:

Parameters: {
  "utf8"=>"✓",
  "authenticity_token"=>"XQI4y7x7CSjxUhdYvEv2bLEjitwCfXxeTBUU3+kYS4g=",
  "user"=> {
    "email"=>"[email protected]",
    "forename"=>"You",
    "surname"=>"Jiii",
    "password"=>"[FILTERED]",
    "password_confirmation"=>"[FILTERED]",
    "artist_attributes" => {
      "bio"=>"NERVO is awesome!",
      "phone_number"=>"",
      "city"=>"",
      "country"=>"Afghanistan"
    }
  },
  "commit"=>"Edit profile"}

person Robert Audi    schedule 02.02.2013    source источник
comment
Где вы используете virtual attribute в форме? Вы можете опубликовать или проверить журнал того, что отправляется в params?   -  person Rahul Tapali    schedule 02.02.2013
comment
Если вы используете его в :artist форме, то он должен current_user.artist_attributes = params[:user][:artist].delete(:artist_attributes)   -  person Rahul Tapali    schedule 02.02.2013
comment
Я добавил журнал хэша params.   -  person Robert Audi    schedule 02.02.2013
comment
у вас есть bio, phone_number и другие столбцы в пользовательской таблице??   -  person Rahul Tapali    schedule 02.02.2013
comment
Нет, я хочу, чтобы artist_attributes был виртуальным атрибутом. Это будет хеш, который содержит биографию, номер телефона и т. д. Затем, когда я установил виртуальный атрибут artist_attributes, я могу вручную обрабатывать то, что находится в хэше.   -  person Robert Audi    schedule 02.02.2013
comment
как ты говоришь это nil ? Вы не можете использовать print(p) для печати в журнал. Попробуйте использовать logger.debug вместо p. Думаю, сработает   -  person Rahul Tapali    schedule 02.02.2013


Ответы (1)


Попробуй это:

Изменять

current_user.artist_attributes = params[:user].delete(:artist_attributes)

To

if current_user.update_attributes(params[:user])
  # happy result
end

Вложенные атрибуты должны автоматически обрабатываться Rails. Если вам нужен собственный сеттер, определите artist_attributes=, и все будет хорошо. Я считаю, что Rails 4 будет поддерживать хеш-значения в Postgresql. А пока посмотрите здесь Rails 3: http://travisjeffery.com/b/2012/02/using-postgress-hstore-with-rails/

Редактировать

Согласно вашему комментарию, я бы не стал хранить его в виртуальном атрибуте, если цель состоит в том, чтобы просто отправить его в ваш API.

# Controller
def update
  if User.update_artist(params[:user][:artist_attributes])
    # happy thoughts
  end
end

# User model
def update_artist(artist_attributes)
  begin
    # API call
  rescue api exception
    log a message like "Couldn't update at this moment"   
  end
end
person mathieugagne    schedule 02.02.2013
comment
Проблема в том, что модель Artist на самом деле является моделью без таблиц, мне нужно обновить художника через вызов API к другому приложению. Я пытаюсь сохранить хэш artist_attributes в виртуальном атрибуте. Если мне удастся это сделать, то я в порядке, но, похоже, это не работает... - person Robert Audi; 02.02.2013
comment
Ваше редактирование вашего ответа предполагает, что я не хочу одновременно обновлять данные пользователя. Мне удалось сохранить то, что я хотел, в виртуальном атрибуте, мне просто нужно было сериализовать этот атрибут в хэш. У меня появилась эта идея благодаря сообщению в блоге, на которое вы ссылаетесь. Так что я приму твой ответ. Теперь у меня другая проблема, но это выходит за рамки первоначального вопроса. Большое спасибо! - person Robert Audi; 02.02.2013