0

I have the following User model with a artist_attributes virtual attribute:

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

  belongs_to :artist
  accepts_nested_attributes_for :artist, update_only: true
end

Here is the artist model:

class Artist < ActiveRecord::Base
  has_one :user
end

The problem is that the virtual attribute is not being set. For example, here my user controller:

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

And here is the form that is submitted:

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

Why isn't the artist_attributes virtual attribute not being set? Is it because of the nested form?

Update

Here is the params hash after I submit the form:

Parameters: {
  "utf8"=>"✓",
  "authenticity_token"=>"XQI4y7x7CSjxUhdYvEv2bLEjitwCfXxeTBUU3+kYS4g=",
  "user"=> {
    "email"=>"youjiii@gmail.com",
    "forename"=>"You",
    "surname"=>"Jiii",
    "password"=>"[FILTERED]",
    "password_confirmation"=>"[FILTERED]",
    "artist_attributes" => {
      "bio"=>"NERVO is awesome!",
      "phone_number"=>"",
      "city"=>"",
      "country"=>"Afghanistan"
    }
  },
  "commit"=>"Edit profile"}
Robert Audi
  • 8,019
  • 9
  • 45
  • 67
  • Where are you using `virtual attribute` in form? can you post or check log that what are being sent in `params`? – Rahul Tapali Feb 02 '13 at 16:49
  • If you are using it in `:artist` form then it should `current_user.artist_attributes = params[:user][:artist].delete(:artist_attributes)` – Rahul Tapali Feb 02 '13 at 16:51
  • I added a log of the params hash. – Robert Audi Feb 02 '13 at 16:57
  • you have `bio`, `phone_number` and others as columns in user table?? – Rahul Tapali Feb 02 '13 at 17:03
  • No, I want `artist_attributes` to be a virtual attribute. It will be a hash that contains bio, phone_number, etc. Then when I have set the `artist_attributes` virtual attribute then I can deal with what's in the hash manually. – Robert Audi Feb 02 '13 at 17:05
  • how are you saying its `nil` ? You can't use `print`(p) to print to log. Try using `logger.debug` instead of `p`.. I think it will work – Rahul Tapali Feb 02 '13 at 17:35

1 Answers1

1

Try this:

Change

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

To

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

Nested attributes should be handled automatically by Rails. If you need a custom setter, define artist_attributes= and you should be good. I believe Rails 4 will support hash values in Postgresql. Meannwhile look here for Rails 3: http://travisjeffery.com/b/2012/02/using-postgress-hstore-with-rails/

Edit

According to your comment, I wouldn't store it in a virtual attribute if the goal is simply to send it to your 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
mathieugagne
  • 2,465
  • 1
  • 17
  • 18
  • The problem is that the Artist model is actually a tableless model, I need to update the artist via an API call to another application. What I am trying to do is to store the `artist_attributes` hash in a virtual attribute. If I can manage to do that then I'm sorted, but it doesn't seem to work... – Robert Audi Feb 02 '13 at 17:18
  • Your edit of your answer assumes that I don't want to update the user details at the same time. I managed to store what I wanted in a virtual attribute, I just needed to serialize this attribute to a Hash. I had this idea thanks to the blog post you linked. So I'm gonna accept your answer. Now I have a different problem but that's out of the scope of the initial question. Thanks a lot! – Robert Audi Feb 02 '13 at 17:36