paperclip custom path and url for polymorphic associations - ruby-on-rails-3

I am using attachment model as polymorphic association. How to change path and url parameters based on the associations.
Attachment Model
class Attachment < ActiveRecord::Base
belongs_to :user
belongs_to :attachable, :polymorphic => true
has_attached_file :attachment,
:url => "/attachments/:id/:basename.:extension",
:path => ":rails_root/public/attachments/:id/:basename.:extension",
:default_url => "/attachments/original/no-file.txt"
end
Project Model
class Project < ActiveRecord::Base
...
has_many :attachments, :as => :attachable, :dependent => :destroy
end
Client
class Client < ActiveRecord::Base
...
has_many :attachments, :as => :attachable, :dependent => :destroy
end
following path files are saving fine.
:path => ":rails_root/public/attachments/:id/:basename.:extension",
but I need to save files based on association like, for this how do pass the parameters to 'path'. 'attachable_type' defines the which association upload file belongs
/attachments/project/
/attachments/client/

You can use Paperclip Interpolations. Interpolations allows you to call a method to determine the value of a part of the path.
class Attachment < ActiveRecord::Base
belongs_to :user
belongs_to :attachable, :polymorphic => true
Paperclip.interpolates :attached_to do |attachment, style|
attachment.instance.attachable.class.to_s.downcase
end
has_attached_file :attachment,
:url => "/attachments/:id/:basename.:extension",
:path => ":rails_root/public/attachments/:attached_to/:id/:basename.:extension",
:default_url => "/attachments/original/no-file.txt"
end

has_attached_file :attachment, :path => ":rails_root/public/attachments/#{lambda { |a| a.instance.images_path? ? 'project' : 'client' }}/:id/:basename.:extension"
def images_path?
if your pretty condition
#return true
else
#return false
end
end

Related

Is it possible to have associations alias in a Rails model?

I have a model with two has_many associations that serve one logical purpose, and I want to alternate between the two depending on some conditions. I can have a convenience method for that, but then I can't use it in has_many :through associations.
Is there a nice way out?
UPD: the model's code:
# encoding: UTF-8
class User < ActiveRecord::Base
set_table_name 'clients'
devise(:database_authenticatable,
#:registerable,
:recoverable,
:rememberable,
:trackable,
:validatable,
#:token_authenticatable,
#:confirmable,
#:lockable
#:timeoutable,
#:omniauthable
)
def email_required?
false
end
# Setup accessible (or protected) attributes for your model
attr_accessible(:email, :login, :password, :password_confirmation, :remember_me, # used by devise
:address, :phone, :description)
attr_accessible :name, :address, :phone, :description
validates :name, :presence => true
has_many :slaves, :class_name => 'User', :foreign_key => 'master_id',
:inverse_of => :master, :dependent => :destroy
belongs_to :master, :class_name => 'User', :foreign_key => 'master_id',
:inverse_of => :slaves
def slave?
master.present?
end
def master?
not slave?
end
validate :slaves_cannot_have_slaves
has_many :master_facilities, :class_name => 'Facility', :foreign_key => 'client_id'
has_many :analytics_profiles, :class_name => 'AnalyticsProfile', :foreign_key => 'owner_id',
:inverse_of => :owner, :dependent => :destroy
has_many :facility_permissions
has_many :slave_facilities, through: :facility_permissions, source: :facility, autosave: true
has_many :units, :through => :facilities, :foreign_key => 'facility_id'
# masters and slaves have different ways of accessing their facilities
# BUT! It's not a true association so a lot of code (e.g. draper) will fail
def facilities
if master?
master_facilities
else
slave_facilities
end
end
def dead_units
self.units.keep_if(&:dead?)
end
private
def slaves_cannot_have_slaves
unless master? or slaves.empty?
errors.add :slaves, 'Slaves cannot have slaves'
end
end
end
If I understood the problem right and the problem is the facilities association, which is implemented via master_facilities or slave_facilities association - why not taking the base behavior out to a module/class and include/inherit it in your concrete classes which will implement the facilities method differently.

Paperclip custom path with id belongs_to

I'm using paperclip inside a project.
The concerned model look like this :
class Asset < ActiveRecord::Base
has_paper_trail # Track model with paper_trail
has_attached_file :image, :styles => { :medium => "300x300>"},
:path => ":rails_root/public/attachments/project_#{:project_id}/ressources/:basename_:style.:extension"
belongs_to :project
end
As you see I want to have the id of concerned project in my image path, how can I make this ?
Try this
has_attached_file :image, :styles => { :medium => "300x300>"},
path => ":rails_root/public/attachments/:project_id/ressources/:basename_:style.:extension"
and then write
Paperclip.interpolates :project_id do |attachment, style|
"project_#{attachment.instance.project_id}"
end

ActiveAdmin customize view for has_many :through

I'm working on a ActiveAdmin app with this models :
User
class User < ActiveRecord::Base
# A User has many roles for interact on a project
has_many :roles, :dependent => :destroy
has_many :projects, :through => :role
end
Role
class Role < ActiveRecord::Base
belongs_to :user
belongs_to :project
end
Project
class Project < ActiveRecord::Base
# A project has many roles for interact
has_many :roles, :dependent => :destroy
has_many :users, :through => :role
accepts_nested_attributes_for :roles
end
To add users with a role on each project I make this form :
form do |f|
f.inputs "Details" do # Project's fields
f.input :title
f.input :code
end
f.has_many :roles do |app_f|
app_f.inputs do
if !app_f.object.nil?
app_f.input :_destroy, :as => :boolean, :label => "Destroy?"
end
app_f.input :user
app_f.input :senior_author
end
end
f.buttons
end
My first question is how can I make a with user.firstname + user.lastname. Actually I have something like this :
#<User:0x007fb98a7d6568>
Second question is my Role model is a list of boolean attributes :
:senior_author
:first_author
:viewer
....
Can I make a with that ?
Another solution would be to just define to_s in the model:
def to_s
"#{email} | #{firstname} #{lastname}"
end
No need to set :label_method.
Just add :label_method => lambda:
app_f.input :user, :label_method => lambda{|u| "#{u.email} | #{u.firstname} #{u.lastname}" }
I fix it by adding this method to models/user.rb
# format label for formtastic dropdown menu
def to_label
"#{email} | #{firstname} #{lastname}"
end
And I use it like this :
app_f.input :user, :include_blank => false, :label_method => :to_label

Active admin has_many through delete association

I'm currently making association like this :
show do
h3 project.title
panel "Utilisateurs" do
table_for project.roles do
column "Prenom" do |role|
role.user.firstname
end
column "Nom" do |role|
role.user.lastname
end
column "email" do |role|
role.user.email
end
column "Role" do |role|
role.role_name.name
end
end
end
end
# override default form
form do |f|
f.inputs "Details" do # Project's fields
f.input :title
f.input :code
end
f.has_many :roles do |app_f|
app_f.inputs do
# if object has id we can destroy it
if app_f.object.id
app_f.input :_destroy, :as => :boolean, :label => "Supprimer l'utilisateur du projet"
end
app_f.input :user, :include_blank => false, :label_method => :to_label
app_f.input :role_name, :include_blank => false
end
end
f.buttons
end
I have the following associations :
Project
has_many :roles, :dependent => :destroy
has_many :users, :through => :role
User
has_many :roles, :dependent => :destroy
has_many :projects, :through => :role
Role
belongs_to :user
belongs_to :project
belongs_to :role_name
RoleName
has_many :roles
When I try to destroy user association through my form nothing happen, any idea to solve this ?
Or to add delete link to my show block ?
Try to add accepts_nested_attributes_for to your Project model (and roles_attributes to attr_accessible):
class Project < ActiveRecord::Base
has_many :roles, :dependent => :destroy
has_many :users, :through => :role
accepts_nested_attributes_for :roles, :allow_destroy => true
attr_accessible :roles_attributes, (+ all you had here before)
...
end
allow_destroy: true is the root of this issue.

How do I delete a record from all tables it is referred to?

Good morning fellow Overflowers,
Small problem with model associations. I have these model associations:
class Categorization < ActiveRecord::Base
belongs_to :exhibit
belongs_to :category
end
class Category < ActiveRecord::Base
has_many :categorizations
has_many :exhibits, :through => :categorizations
acts_as_indexed :fields => [:title]
validates :title, :presence => true, :uniqueness => true
end
class Exhibit < ActiveRecord::Base
has_many :categorizations
has_many :categories, :through => :categorizations, :source => :category
acts_as_indexed :fields => [:title, :bulb]
validates :title, :presence => true, :uniqueness => true
belongs_to :foto, :class_name => 'Image'
end
So, essentially Categorization ends up with these columns (date/time stamps omitted):
categorization_id, exhibit_id and category_id.
My problem is that when I delete an Exhibit, its reference on the Categorization table is not deleted thus getting a DB error on my view. I have to first unassign the Exhibit from any Category and then delete it safely. Or (given for example that the Exhibit I delete has :exhibit_id=>'1') when I give in the rails console: Categorization.find_by_exhibit_id(1).destroy
Thanks for any help!!
You can set the :dependent options on associations that you want Rails to follow when you delete their parents:
class Exhibit < ActiveRecord::Base
has_many :categorizations, :dependent => :destroy
...
end