Что означает AssociationTypeMismatch в ruby ​​on rails? я получаю эту ошибку с вложенными атрибутами

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

У меня есть:

Модель микропоста (имеет_одно фото) Модель фотоальбома (имеет_много фото) Модель фото (принадлежит_микропосту, принадлежит_фото_альбому)

Пользователь заполняет текст в текстовой области и выбирает фотографию. После отправки таблица микросообщений обновляется данными, связанными с микросообщениями, такими как контент, created_at и т. д.

В то же время я хочу, чтобы моя таблица фотографий (фотомодель) обновлялась с выбором фотографий, сделанным пользователем, но с правильным фотоальбомом. Если вы посмотрите ниже, вы увидите в моем users_controller значение переменной экземпляра @photo. Это гарантирует, что загруженная фотография будет связана с правильным фотоальбомом, который называется «альбом микросообщений». Его цель — связать все фотографии, связанные с микропостами.

У меня есть Users_controller:

  def new
     @user = User.new 
     @micropost = Micropost.new(:user_id => users_id)
     @photo = Photo.new(:photo_album_id => PhotoAlbum.where(:user_id => current_user.id, :album_title => "microposts album").first.id)
  end

Из предыдущего вопроса, который я задал, было установлено, что мне нужно использовать accepts_nested_attributes_for, fields_for, чтобы иметь возможность обновлять более одной модели с помощью одной формы. Вот как я все настроил.

Модель микропостов:

class Micropost < ActiveRecord::Base

  belongs_to :user
  has_one  :photo
  accepts_nested_attributes_for :photo
  attr_accessible :content, :user_id, :poster_id, :username, :image, :remote_image_url

end

Фотомодель:

class Photo < ActiveRecord::Base

  belongs_to :photo_album

    attr_accessible :photo_album_id, :photo_title, :image, :remote_image_url
    mount_uploader :image, ImageUploader

end

Наконец, вот форма микросообщения:

= form_for @micropost, :remote => true do |f|
    = f.fields_for @photo do |p|
        = p.file_field :image
    = f.hidden_field :user_id
    = f.text_area :content
    = f.submit "Post"

Сначала я получил сообщение об ошибке:

ActiveModel::MassAssignmentSecurity::Error (Can't mass-assign protected attributes: photo):

Я был немного сбит с толку, потому что думал, что атрибуты назначаются автоматически. По крайней мере, это то, что я читал в документах. В любом случае, я пошел дальше и добавил :photo в белый список модели микросообщения attr_accessible.

Появилась первая ошибка, а потом появилась вот эта:

ActiveRecord::AssociationTypeMismatch (Photo(#2169424320) expected, got ActiveSupport::HashWithIndifferentAccess(#2157396720)):

Возможно, я неправильно понял, как работает эта функция, но я прочитал это, а также просмотрел документ API 3.2.3, но не там, где я ошибаюсь.

Я был бы очень признателен за помощь в том, чтобы заставить это работать.

Заранее благодарю и надеюсь, что длинный пост вас оттолкнул. Просто подумал, что предоставление всей этой информации поможет людям понять, что я пытаюсь сделать лучше.

С уважением

Обновление: использование :photo_attributes вместо фотографий приводит к следующей ошибке:

Started POST "/microposts" for 127.0.0.1 at 2012-05-10 21:01:11 +0100
[02b23327ad83000f75c418d8739e7f49] [127.0.0.1] Processing by MicropostsController#create as JS
[02b23327ad83000f75c418d8739e7f49] [127.0.0.1]   Parameters: {"micropost"=>{"photo"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x00000102c293d8 @original_filename="7seriesbmw.jpeg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"micropost[photo][image]\"; filename=\"7seriesbmw.jpeg\"\r\nContent-Type: image/jpeg\r\n", @tempfile=#<File:/var/folders/fh/fhADKPjGG8qSuCeoHCTNYE+++TI/-Tmp-/RackMultipart20120510-14787-1e1mrhh>>}, "user_id"=>"2", "content"=>"ioo"}, "commit"=>"Post", "utf8"=>"✓", "authenticity_token"=>"/y8Lr+e7xgabt60GWxnMGvCtIi7IjqrYDoA84vAqYcE=", "remotipart_submitted"=>"true", "X-Requested-With"=>"IFrame", "X-Http-Accept"=>"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01"}
[02b23327ad83000f75c418d8739e7f49] [127.0.0.1]   User Load (0.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
[02b23327ad83000f75c418d8739e7f49] [127.0.0.1] Completed 500 Internal Server Error in 649ms
[02b23327ad83000f75c418d8739e7f49] [127.0.0.1] 
ActiveModel::MassAssignmentSecurity::Error (Can't mass-assign protected attributes: photo):
  app/controllers/microposts_controller.rb:9:in `create'

После изменения attr_accessor обратно на :photo вместо :photo_attributes:

Started POST "/microposts" for 127.0.0.1 at 2012-05-10 21:20:07 +0100
[985e0f204bf7ffac1f7c02fbec35ad9b] [127.0.0.1] Processing by MicropostsController#create as JS
[985e0f204bf7ffac1f7c02fbec35ad9b] [127.0.0.1]   Parameters: {"micropost"=>{"photo"=>{"image"=>#<ActionDispatch::Http::UploadedFile:0x00000102f8a3b0 @original_filename="7seriesbmw.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"micropost[photo][image]\"; filename=\"7seriesbmw.png\"\r\nContent-Type: image/png\r\n", @tempfile=#<File:/var/folders/fh/fhADKPjGG8qSuCeoHCTNYE+++TI/-Tmp-/RackMultipart20120510-15197-9rt2xn>>}, "user_id"=>"2", "content"=>"pp"}, "commit"=>"Post", "utf8"=>"✓", "authenticity_token"=>"/y8Lr+e7xgabt60GWxnMGvCtIi7IjqrYDoA84vAqYcE=", "remotipart_submitted"=>"true", "X-Requested-With"=>"IFrame", "X-Http-Accept"=>"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01"}
[985e0f204bf7ffac1f7c02fbec35ad9b] [127.0.0.1]   User Load (0.4ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
[985e0f204bf7ffac1f7c02fbec35ad9b] [127.0.0.1] Completed 500 Internal Server Error in 452ms
[985e0f204bf7ffac1f7c02fbec35ad9b] [127.0.0.1] 
ActiveRecord::AssociationTypeMismatch (Photo(#2180069640) expected, got ActiveSupport::HashWithIndifferentAccess(#2153916820)):
  app/controllers/microposts_controller.rb:9:in `create'

Действие создания контроллера микросообщений:

def create


    if params[:micropost][:user_id].to_i == current_user.id
     @micropost = current_user.microposts.build(params[:micropost])

     @comment = Comment.new(:user_id => current_user.id)
        respond_to do |format|
            if @micropost.save


            format.js   { render :post_on_springboard }

            end
        end
    else

    user = User.find_by_username(params[:micropost][:username])
    @micropost = user.microposts.build(params[:micropost])
    if @micropost.save

    UserMailer.new_wall_post_notification(user, current_user).deliver if user.email_notification == 1

    flash[:success] = "Micropost posted"
    redirect_to root_path+user.username
    else
    flash[:error] = "#{@micropost.errors.full_messages.first}"
    redirect_to root_path+user.username
    end

    end

end

person LondonGuy    schedule 10.05.2012    source источник


Ответы (4)


Многое из того, что вы пытаетесь сделать, касается отношений, и вы должны быть в состоянии заставить работать соглашения rails на вас. Если вы начинаете писать кучу кода для чего-то довольно простого с помощью рельсов, это обычно плохой знак.

На самом деле я бы сосредоточился сначала на ваших маршрутах.

Например, если вы вкладываете фотографии в альбомы, например.

resources :albums do
  resources :photos
end

Тогда вы получите много путей и функций, которые вы хотите.

Убедитесь, что в ваших формах используются такие элементы, как form_for [@album, @post], которые будут сочетаться с вашим accepts_nested_attributes_for.

person Michael Durrant    schedule 10.05.2012
comment
Пойду еще раз читать про маршруты. Существуют ли какие-либо другие конкретные страницы направляющих рельсов, страницы API, на которые вы могли бы направить меня, если я правильно понимаю, они помогут мне достичь того, чего я пытаюсь достичь в этом вопросе? Я был бы признателен за это. Спасибо - person LondonGuy; 11.05.2012

попробуйте добавить :photo_attributes в свой список attar_accessible в вашей модели микросообщений

Я думаю, это должно устранить первую ошибку.

Все еще смотрю на второй.

Можете ли вы опубликовать полную трассировку стека из формы, это может быть проблема с модулями вашего контроллера.

person TheIrishGuy    schedule 10.05.2012
comment
Когда я меняю его на photo_attributes, возвращается первая ошибка. Я добавил полную трассировку стека для сообщения в свой вопрос. - person LondonGuy; 11.05.2012

изменение

f.fields_for @photo 

to

f.fields_for :photo 

и добавление

@micropost.build_photo(:photo_album_id => :photo_album_id => current_user.photo_albums.find_by_album_title("microposts album").id) 

на мой microposts_controller исправил мою проблему

person LondonGuy    schedule 11.05.2012

person    schedule
comment
Это более полезно, когда вы пишете какое-то описание того, что вы делаете, вместо того, чтобы просто сбрасывать какое-то кодовое решение. - person sphair; 14.10.2013