Reputation: 11098
I have a system setup where users can post microposts (basically status updates) and upload a photo to go with the micropost.
I have:
Micropost model (has_one photo) Photo_album model (has_many photos) Photo model (belongs_to micropost, belongs_to photo_album)
User fills in text in text area and selects a photo. Upon submission the microposts table is updated with micropost related data such as content, created_at etc.
At the same time I want my photos table (Photo model) updated with the photo selection the user made but the correct photo album. If you look below you can see in my users_controller the instance variable @photo's value. This insures that the photo uploaded is linked to the correct photo album which is named "microposts album". It's purpose is to link up to all micropost related photos.
I have a 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
From a previous question I asked it was established I needed to use accepts_nested_attributes_for, fields_for in order to be able to update more than one model with one form. This is how I've set things up.
Micropost model:
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
Photo model:
class Photo < ActiveRecord::Base
belongs_to :photo_album
attr_accessible :photo_album_id, :photo_title, :image, :remote_image_url
mount_uploader :image, ImageUploader
end
Finally here is the micropost form:
= 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"
At first I got the error:
ActiveModel::MassAssignmentSecurity::Error (Can't mass-assign protected attributes: photo):
I was slightly confused because I thought the attributes were assigned automatically. At lesast thats what I read in the docs anyway. Anyway I went ahead and added :photo to the micropost model attr_accessible white list.
That first error went then I got this one:
ActiveRecord::AssociationTypeMismatch (Photo(#2169424320) expected, got ActiveSupport::HashWithIndifferentAccess(#2157396720)):
Maybe I've misunderstood how this feature works but I've read through this and also looked at the 3.2.3 api doc but not where I'm going wrong.
I would really appreciate some help with getting this to work.
Thanks in advance and I hope the long post was off putting. Just thought providing all this info would make people understand what I'm trying to do better.
Kind regards
Update: Using :photo_attributes instead of photos gives me the following error:
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'
After changing the attr_accessor back to :photo instead of :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'
Microposts controller create action:
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
Upvotes: 1
Views: 1388
Reputation: 311
class Organization < ActiveRecord::Base
has_one :picture, :dependent => :destroy
accepts_nested_attributes_for :picture
attr_accessible :address, :contect_number, :email, :name, :type_of_organization, :picture_attributes
end
class Picture < ActiveRecord::Base
belongs_to :organization
mount_uploader :avatar, AvatarUploader
attr_accessible :avatar, :organization_id
end
class OrganizationsController < ApplicationController
load_and_authorize_resource
def new
@organization = Organization.new
# @organization.attributes = Picture.new
# @picture = Picture.new
end
def create
logger.info "++++++++inside the organisation controller++++++++++"
logger.info params[:organization].inspect
@org = Organization.new(params[:organization])
if @org.save
@picture = Picture.new(:avatar => params[:organization][:picture_attributes][:avatar])
@picture.organization_id = @org.id
@picture.save
logger.info "---------- inside Avtar controller ---------------"
logger.info @picture.inspect
session[:org_id] = @org.id
redirect_to new_admin_user_path :notice => 'Organization created successfully.'
else
render 'new'
end
end
end
<div>
<h4>FillUp organization details.</h4>
<%= form_for @organization, :url => organizations_path do |f| %>
<%= f.label :name, "Name" %>
<%= f.text_field :name %>
<%= f.label :contect_number, "Contact Number" %>
<%= f.text_field :contect_number %>
<%= f.label :address, "Address" %>
<%= f.text_field :address %>
<%= f.label :website, "Website" %>
<%= f.text_field :email %>
<%= f.label :company_type, "Type" %>
<%= f.text_field :type_of_organization %>
<%= f.fields_for :picture_attributes, :html => { :multipart => true } do |p| %>
<%= p.label :avatar, "My Avatar" %>
<%= p.file_field :avatar %><br/>
<%end%>
<%= f.submit :Create, :class => 'btn btn-primary' %>
<%end%>
</div>
Upvotes: 0
Reputation: 11098
changing
f.fields_for @photo
to
f.fields_for :photo
and adding
@micropost.build_photo(:photo_album_id => :photo_album_id => current_user.photo_albums.find_by_album_title("microposts album").id)
to my microposts_controller fixed my issue
Upvotes: 0
Reputation: 96484
A lot of what you are trying to do concerns relationships and you shuld be able to get rails conventions working for you. If you start writing a bunch of code for somehting fairly simple with rails that's usually a bad sign.
I would focus first on your routes actually.
If you nest photo inside albums for instance, e.g.
resources :albums do
resources :photos
end
Then you will get a lot of the paths and functionality that you want.
Make sure your forms use things like form_for [@album, @post]
which will go along with your accepts_nested_attributes_for
Upvotes: 1
Reputation: 2573
try adding :photo_attributes to your attar_accessible list in your micropost model
That should resolve the first error, I think.
Still looking into the second.
Can you post the complete stack trace from the form, it might be an issue with your controller mothods.
Upvotes: 0