I have a polymorhpic model as follows:
class Upload < ActiveRecord::Base
belongs_to :uploadable, :polymorphic => true
has_attached_file :photo
end
class Message < ActiveRecord::Base
has_one :upload, :as => :uploadable, :dependent => :destroy
end
The user uploads a photo in a fancy box iframe using the ajax hack with the jquery-file-upload plugin.
The uploaded photo is saved in the uploads table without uploadable_id or uploadable_type as I don't have the parent Message yet.
How can I update the Upload model with the Message id and type when I save the Message?
You can try this:
#message = Message.new(params[:message])
#message.upload = #upload
#message.save
Related
I am facing a weird behaviour. This is my scenario.
class Message < ActiveRecord::Base
belongs_to :user, :foreign_key => "from_user_id"
has_many :message_recipients, :include => [:user], :dependent => :destroy
has_many :recipients, :through => :message_recipients, :source => :user
end
class MessageRecipient < ActiveRecord::Base
belongs_to :user
belongs_to :message, :include => :message_recipients
end
class User < ActiveRecord::Base
acts_as_paranoid
has_many :message_recipients
end
I am creating a new message and pushing value to its recipients.
#message=Message.new(:body => "Hi",:from_user_id => session[:user])
#message.recipients.push(User.find(params[:message_recipient_id]))
#message.save
The above operation saves the record in message correctly but fails to trigger the message_recipient record. But if i perform the above code removing the acts_as_paranoid gem, then it works fine. Is there any work around to solve this issue?
Solution 1:
Instead of calling new on Message model we can use create on Message model. So the record will be created and then i can push the data inside the recipients.Its like creating parent record and using its id i am creating child record. So there is no need for trigerring and it works fine.
Suggestions are welcome.
It works fine with rails 3.2.12 but fails with rails 3.2.13. I am confused with this behaviour.
This is EXTREMELY bizarre. I'm upgrading a Rails 2.3.12 app and running into this same problem over and over again. I'm stumped and nothing else out there seems to touch on it.
I have two models:
class User < ActiveRecord::Base
has_many :logs, :class_name => 'UserLog'
end
and
class UserLog < ActiveRecord::Base
attr_accessor :site_id, :controller, :action, :url, :session
belongs_to :user
validates_presence_of :user
end
then in another controller I'm doing this:
def log_user_activity
#current_user.logs.create(:site_id => #site.id, :controller => params[:controller],
:action => params[:action], :url => request.path,
:session => request.session_options[:id]) if #current_user
end
as you can see, it's pretty straightforward but when I call log_user_activity I'm getting this:
Can't mass-assign protected attributes: site_id, controller, action, url, session
HOWEVER, if I change all my creates or builds to this:
def log_user_activity
log = #current_user.logs.new
log.site_id = #site.id
log.controller = params[:controller]
log.action = params[:action]
log.url = request.path
log.session = request.session_options[:id]
log.save
end
then it works fine!?
Has anyone seen this? Any clues?
In class UserLog, add the following:
attr_accessible :site_id, :controller, :action, :url, :session
The reason you have to use attr_accessible is most likely because you are utilizing a plugin that is relying on this being present for a model. It has happened to all of us and is a royal pita)
Once attr_accessible is designated for a class, then any attribute that is not specified as 'accessible' will not be allowed to be updated.
I have two models in Rails 3 - a User model and a Profile model.
class User < ActiveRecord::Base
has_one :profile, :dependent => :destroy
end
class Profile < ActiveRecord::Base
belongs_to :user
end
They are scoped in my routes.rb file, as such:
resources :users do
resources :profiles
end
So now, my form to create a profile reads like this (Using SimpleForm):
<%= simple_form_for([#user, #profile]) do |f| %>
<%= f.error_notification %>
...(Other Inputs)
<% end %>
However, the user ID doesn't seem to be automatically sent to the profile model as I had assumed. Do I have to set that manually through the controller? Or am I missing something?
You should start by making sure that the relationship between User and Profile is indeed working correctly. You've actually put "has_one :user" in your User model, when I think you mean:
class User < ActiveRecord::Base
has_one :profile, :dependent => :destroy
end
In order to send the user ID with the form, the form should be on a page with a URL of something like "localhost:3000/users/5/profiles/new" which you can link to with the helper "new_user_profile_path(5)", for a user with ID 5.
When you submit the form, it will hit the create action in your ProfilesController. The following should result in the creation of the profile:
def create
#user = User.find(params[:user_id])
#profile = #user.build_profile(params[:profile])
#profile.save!
end
add :method => :post to your form since ur html request is GET which should be POST
simple_form_for([#user, #profile], :method => :post) do |f| %>
For example
class User < ActiveRecord::Base
has_one :avatar, :dependent => :destroy
end
class Avatar < ActiveRecord::Base
belongs_to :user
end
What if I have a User with an Avatar and then do something like
old_avatar = user.avatar
new_avatar = Avatar.new
user.avatar = new_avatar
user.save
old_avatar.destroy
So I don't want do the last command manually (destroy). Is there any options for has_many to autodestroy old object? Or many it's better use something else instead of avatar= method?
Thank you.
Why not update old avatar instead of creating new one like:
avatar = Avatar.find_or_initialize_by_user_id(:user_id => user.id)
avatar.attributes = new_attributes
avatar.save
Also, you might create after_save callback inside Avatar model if you like.
I have a scenario where i am uploading files dynamically using ajax remotipart, then later i assign those uploaded files to any model. I have such settings in uploader.
class DocumentUploader < CarrierWave::Uploader::Base
storage :file
def store_dir
"uploads/#{model.class.to_s.pluralize.underscore}/#{model.documentable_type.to_s.pluralize.underscore}/#{model.documentable_id}"
end
def extension_white_list
%w(doc pdf docx xls xlsx)
end
end
class Document < ActiveRecord::Base
mount_uploader :document, DocumentUploader
belongs_to :documentable, :polymorphic => true
validates :document, :presence => true
validates :description, :presence => true
end
class Post < ActiveRecord::Base
has_many :documents, :as=>:documentable
end
When i upload a document without providing documentable source, it uploads the files to /uploads/documents/uploaded_file.doc
But when i assign that document to some other model like
#post = Post.first
#post.documents << Document.last
#post.save
It save the record correctly and when get url of the file like #post.documents.first.document.url it gave url like this /uploads/documents/posts/10212/uploaded_file.doc where the file was not available.
How can i handle such assignment of pre-existing uploads?
I came here while googling and thought some people might help this piece of code I'm using in a controller to re-assign a file (here it's an image) to another model which is handled with CarrierWave:
def create
temporary_image = TemporaryImage.find(params[:temporary_image][:id])
#player = Player.new(params[:player])
#player.image = File.open(temporary_image.image.current_path)
# now you can handle #player.image as if it was
# originally assigned by CarrierWave
end
where
class Player < ActiveRecord::Base
attr_accessible :image
mount_uploader :image, PlayerImageUploader
end
and
class TemporaryImage < ActiveRecord::Base
attr_accessible :image
mount_uploader :image, TemporaryImageUploader
end
I'm using this in conjunction with an ajax fileupload (stored via TemporaryImage) where the image is immediately presented and can then be cropped. After cropping it is stored within Player.
I solved the issue by doing lot of hit and trail. but finally solved.
class Document < ActiveRecord::Base
mount_uploader :document, DocumentUploader
belongs_to :documentable, :polymorphic => true
validates :document, :presence => true
validates :description, :presence => true
after_update :relocate_files
def relocate_files
src_file = Rails.root.join("public", "uploads", "documents", document.url.split("/").last)
dst_file = Rails.root.join("public", "uploads", "documents", documentable_type.pluralize.underscore, documentable_id.to_s, document.url.split("/").last)
unless FileTest.exists?(dst_file)
FileUtils.mkdir_p(File.dirname(dst_file))
FileUtils.mv(src_file, dst_file)
end
end
end