I have seen http://rails-bestpractices.com/posts/15-the-law-of-demeter for delegation, I like this and I want to customize like below .
Case1 :
class Application < ActiveRecord::Base
belongs_to :user
delegate :name, :to => :user
has_one :repair, :dependent => :destroy
delegate :estimated_amount, :to => :repair
has_one :dealership, :through => :booking
end
class User < ActiveRecord::Base
def name
return some value
end
end
I have called Application.first.user_name => undefined method `user_name' for #<Application:0xb186bf8>
Case2: I have called Application.first.repair_estimated_amount: => undefined method `'repair_estimated_amount' for #<Application:0xb186bf8>
Case3: I have called Application.first.dealership_name: => undefined method `' for #<Application:0xb186bf8>
can any one suggest how to use delegate with has_one relation ?
Thanks in Advance
Prasad
You did not use prefix option, so you should just invoke the method without prefix.
# model.rb
delegate :estimated_amount, :to => :repair
# somewhere else
Application.first.estimated_amount #=> works
Application.first.report_estimated_amount #=> exception!
however, if you pass prefix option:
# model.rb
delegate :estimated_amount, :to => :repair, :prefix => true
# somewhere else
Application.first.estimated_amount #=> exception
Application.first.report_estimated_amount #=> works!
see documentation for delegate()
Related
I have made the following addition to my active admin interface:
action_item :only => :show do
link_to('Approve this article', approve_admin_article_path(article)) if article.approved.nil?
end
member_action :approve, :method => :get do
# do approval
redirect_to :action => :show, :notice => "Approved!"
end
This throws the following error:
undefined method `approved' for
:Arbre::HTML::Article
What I think is happening is Active Admin thinks I'm passing an article tag in, not an article class?
Does anyone know of a work around for this? perhaps aliasing?
Thanks!
class Article < ActiveRecord::Base
attr_accessible :body
# Relations:
belongs_to :articleable, polymorphic: true, :counter_cache => true
has_many :comments, as: :commentable, order: 'created_at DESC', dependent: :destroy
# Validations
validates_presence_of :body
validates_length_of :body, maximum: 15000
end
Found a workaround
There is something fishy when you name your class as 'Article', ActiveAdmin relate to it when rendering as <article> HTML tag - The problem is somewhere in the controller of course because this is where the article object is being generated
So, I override the controller
ActiveAdmin.register Article do
controller do
def show
# grabbing my desired Article and not the <article> tag into some global variable
##myarticle = Article.find(params[:id])
end
end
sidebar :article_details , :only => :show do
ul do
# using the ##myarticle which I know should be initialized
# (you can put .nil? checking here if you want)
li link_to 'Article Images (' + ##myarticle.images.count.to_s + ')' , admin_article_article_images_path(##myarticle)
li link_to 'Article Clips ('+##myarticle.clips.count.to_s + ')' , admin_article_article_clips_path(##myarticle)
end
end
end
Enjoy
Assuming you're having the issue in the 'show' block, you could change the show block to the following:
show do |object|
end
Then you can call object.some_method without the clash. This way you don't need to override the controller.
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 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
Let's say I have:
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class Article < ActiveRecord::Base
has_many :comments, :as => :commentable
end
class Photo < ActiveRecord::Base
has_many :comments, :as => :commentable
#...
end
now I want to find all comments on Jim's photo:
#jims_photo = Photo.where(:of => "Jim")
#photo_comments = Comment.where(:commentable => #jims_photo)
this seems to not work in rails (Rails 3). The generated query seems to not expand the polymorphic object into commentable_id and commentable_type fields:
SQLite3::SQLException: no such column: comments.commentable:
I'm new to ruby and rails so I might be using the paradigm incorrectly but my expectation was that rails automatically expands
:commentable => #jims_photo
to:
:commentable_id => #jims_photo.id, :commentable_type => #jims_photo.class.name
If you want to be really safe with:
:commentable_id => #jims_photo.id, :commentable_type => #jims_photo.class.name
Then I'd recommend replacing .class.name with .base_class (you don't actually need the name: to_s returns name and will be called automatically).
The reason for this is that when ActiveRecord saves the _type for a polymorphic association it'll use base_class to ensure it's not saving a class which itself is a polymorphic one.
If you play with store_full_sti_class you'll probably have to take even more precautions.
I highly recommend looking at Rails' STI code, here.
The guides for Rails are one of the best so I'd suggest you start reading about Polymorphic Associations
You class declarations looks OK and I'm assuming that you're migrations is as well. But just for the sake of it. Let's say it looks like this:
class CreateComment < ActiveRecord::Migration
def change
create_table :comments do |t|
t.string :name
t.references :commentable, :polymorphic => true
# this is the equivalent of
# t.integer :commentable_id
# t.string :commentable_type
t.timestamps
end
end
end
Not if you have a Article or Photo object and you want to get the comments for that object then Thilo's suggestion is right on. All you need to do is this: #jims_photo.comments
If, on the other hand, you have a an instance of the Comment model, you can get the parent like this: #comment.commentable. But if you want to get Jim's photo comments best to do it like that. Otherwise, you'd have to supply as arguments both the :commentable_id and commentable_type. I'm not aware of any finder that expands the polymorphic object into commentable_id and commentable_type fields for you.
But you can always create a class method for that:
def self.find_by_parent(parent)
where(:commentable_id => parent.id, :commentable_type => parent.class.name)
end
Using Rails 3.1 RC4.
My User model has the following:
has_many :emails, :dependent => :destroy
accepts_nested_attributes_for :emails
My Email model has the following:
belongs_to :user
attr_accessible :email, :email_confirmation, :as => :admin
In Rails console:
User.first.update_attributes!({:artist_name => 'foo', :emails_attributes => {0 => {:email => 'foo#blah.com', :email_confirmation => 'foo#foo.com'}}}, :as => :admin)
I get:
WARNING: Can't mass-assign protected attributes: email, email_confirmation
In my Email model, if I remove :as => :admin. Everything works...
Should I be assigning some kind of scope to accepts_nested_attributes_for? Anyone know how this can be fixed?
Issue and solution has been highlighted here.
In summary, an options hash must be passed.