I have a Micropost model and a Gallery model and a Picture model and the pictures either belong to Micropost or Gallery model. I have a micropost form where it accepts_nested_attributes_for :pictures
and have set the associations in models, and, controller micropost create action and strong parameters look like this,
Micropost_controller
def create
@micropost = current_user.microposts.create(micropost_params)
@pictures = @micropost.pictures
@pictures.each do |pic|
pic.update!(gallery_id: params[:gallery_id])
end
...
render 'static_pages/home'
end
def micropost_params
params.require(:micropost).permit(:content, pictures_attributes: [:id, :gal_refs_id, :picture, :_destroy]))
end
The gallery is preset so I have its id which is sent in a hidden field and retrieved in the microposts controller as shown.
Problem is I need to return the @micropost
object so I can update the :gallery_id
, so I cannot use @micropost.save
as it only returns true
or false
and this is the behavior I need to re-render the form if errors occur.
At the moment using create it silently fails and renders the template.
How can I overcome this or is there a better way to do this?
Thanks in advance!
答案 0 :(得分:2)
Try using the below code. If @micropost has no errors, it will create @micropost and you can update its associated objects
def create
@micropost = current_user.microposts.build(micropost_params)
if @micropost.save
# if the object has no errors
@pictures = @micropost.pictures
@pictures.each do |pic|
pic.update!(gallery_id: params[:gallery_id])
end
...
render 'static_pages/home'
else
# show Errors
@micropost.errors
end
end
def micropost_params
params.require(:micropost).permit(:content, pictures_attributes: [:id, :gal_refs_id, :picture, :_destroy]))
end
答案 1 :(得分:1)
Models:
class Micropost
has_many :pictures, as: :imageable, inverse_of: :imageable
end
class Picture
belongs_to :imageable, polymorphic: true
end
class Gallery
has_many :pictures, as: :imageable, inverse_of: :imageable
end
# Note: inverse_of is important here! It allows you to instantiate the
# Picture object without having a Picture object yet.
Controller:
def create
@micropost = micropost.new(micropost_params)
@pictures.each do |picture|
@micropost.pictures.new({
picture: picture,
gallery_id: params[:gallery_id]
})
end
# Note: Pictures will not be saved or persisted in the database until
# .save is called.
# Note: If your Picture object is invalid, Micropost save will also fail
if @micropost.save
# Saved, do something here with the success response
render 'static_pages/home'
else
# Errors
@micropost.errors
end
end
Picture Validation: This is code from my production app, adjust to your needs.
steam_game_details['images'].each do |image|
image_file_name = image.split('/').last.split('?').first
local_picture = picture.where({
picture_file_name: image_file_name
}).first_or_initialize
# Check if the image is nil and whether or not it actually exists on AWS S3
#
if local_picture.picture.nil? || !local_picture.picture.exists?
local_picture.assign_attributes({
picture: open(URI.parse(image)),
picture_file_name: image_file_name # Overwrite the name generated by Paperclip
})
end
end