-
-
Save madwork/7356782 to your computer and use it in GitHub Desktop.
class Attachment < ActiveRecord::Base | |
mount_uploader :attachment, AttachmentUploader | |
# Associations | |
belongs_to :attached_item, polymorphic: true | |
# Validations | |
validates_presence_of :attachment | |
validates_integrity_of :attachment | |
# Callbacks | |
before_save :update_attachment_attributes | |
# Delegate | |
delegate :url, :size, :path, to: :attachment | |
# Virtual attributes | |
alias_attribute :filename, :original_filename | |
private | |
def update_attachment_attributes | |
if attachment.present? && attachment_changed? | |
self.original_filename = attachment.file.original_filename | |
self.content_type = attachment.file.content_type | |
end | |
end | |
end |
# encoding: utf-8 | |
require 'carrierwave/processing/mime_types' | |
class AttachmentUploader < CarrierWave::Uploader::Base | |
include CarrierWave::MimeTypes | |
storage :file | |
def store_dir | |
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" | |
end | |
process :set_content_type | |
end |
class AttachmentsController < ApplicationController | |
before_action :find_attachable | |
def create | |
@attachable.attachments.create attachment_params | |
redirect_to @attachable | |
end | |
private | |
def attachment_params | |
params.require(:attachment).permit(:attachment) | |
end | |
# could be improve and include into concerns | |
# http://api.rubyonrails.org/classes/ActiveSupport/Concern.html | |
def find_attachable | |
params.each do |name, value| | |
return @attachable = $1.classify.constantize.find(value) if name =~ /(.+)_id$/ | |
end | |
end | |
end |
# Required gem ryanb/nested_form | |
# https://github.com/ryanb/nested_form | |
<%= nested_form_for @post, html: { multipart: true } do |f| %> | |
<p><%= f.link_to_add "Add an attachment", :attachments %></p> | |
<%= f.fields_for :attachments do |attachment_form| %> | |
<%= attachment_form.file_field :attachment %> | |
<%= attachment_form.hidden_field :attachment_cache %> | |
<%= attachment_form.link_to_remove "Remove this attachment" %> | |
<% end %> | |
<% end %> |
class Post < ActiveRecord::Base | |
has_many :attachments, as: :attached_item, dependent: :destroy | |
# http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html#method-i-accepts_nested_attributes_for | |
accepts_nested_attributes_for :attachments, allow_destroy: true, reject_if: proc { |attributes| attributes[:attachment].nil? } | |
end |
class PostsController < ApplicationController | |
def new | |
@post = Post.new | |
end | |
def create | |
@post = Post.create post_params | |
redirect_to @post | |
end | |
private | |
def post_params | |
params.require(:post).permit(attachments_attributes: [:id, :attachment, :attachment_cache, :_destroy]) | |
end | |
end |
App::Application.routes.draw do | |
# Concerns must be declared before | |
# http://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Concerns.html | |
concern :attachable do | |
resources :attachments, only: :create | |
end | |
resources :posts, concerns: [:attachable] | |
end |
create_table "attachments", force: true do |t| | |
t.integer "attached_item_id" | |
t.string "attached_item_type" | |
t.string "attachment", null: false | |
t.string "original_filename" | |
t.string "content_type" | |
t.datetime "created_at" | |
t.datetime "updated_at" | |
end | |
add_index "attachments", ["attached_item_type", "attached_item_id"] |
Flawless. Thank you.
I am getting error if try to destroy image "undefined method `name' for nil:NilClass"
Thank you for sharing this.
In my case I did not use nested form. I used the standard form_for and fields_for helpers.
<%= form_for @organization, url: {action: "create"} do |f| %> <%= f.text_field :name %> <%= f.fields_for :image do |image_form| %> <%= image_form.file_field :image %> <%= image_form.hidden_field :image_cache %> <% end %> <%= f.submit "Create" %> <% end %>
For this to send the request with the expected 'image_attributes' parameters and not just a nested 'image' parameter, you need the parent object instance to initialize the nested object.
This means that in the controller or view, you will need to do something like this @organization.build_image
God Bless.
Does this code apply to Rails 5. I have tried this code but nothing gets stored in the database.
Works for me. My only challenge is I added a "Description" and "Order" to my attachments table. I'm trying to figure out how to 'edit' those fields with an edit view/update model without actually uploading a new image. (works if you update the image too)
Form redisplay in case of validation errors doesn't work. I have has_one association.
What should i need to do for that.
Thanks