如何修改 Commontator::Comment(或任何 rails 引擎)?
How to monkey patch Commontator::Comment (or any rails engine)?
我最近才知道猴子补丁这个词,所以我不确定我是否正确。
我正在使用 Commontator gem 在我的博客(Monologue::Post 模型)和我的其他模型上提供评论功能。我 运行 遇到一个问题,我试图从我的评论中获取父对象(即评论的内容)。看起来我必须做三个连接。与其在我的控制器中调用它,我想我可以扩展 gem 的模型以具有一个函数 comment_parent
,该函数 return 父模型。
我有这个:
# config/initializers/comment_model_extenders.rb
module Commontator
class Comment < ActiveRecord::Base
def comment_parent
# do some magic
"return parent here"
end
end
end
我一定是做错了,因为我得到了这个错误:
irb(main):010:0> c=Commontator::Comment
=> Commontator::Comment(id: integer, creator_type: string, creator_id: integer, editor_type: string, editor_id: integer, thread_id: integer, body: text, deleted_at: datetime, cached_votes_up: integer, cached_votes_down:
integer, created_at: datetime, updated_at: datetime)
irb(main):011:0> c.comment_parent
NoMethodError: undefined method `comment_parent' for #<Class:0xab743d0>
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.1.8/lib/active_record/dynamic_matchers.rb:26:in `method_missing'
from (irb):11
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/console.rb:90:in `start'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/console.rb:9:in `start'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/commands_tasks.rb:69:in `console'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands.rb:17:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
编辑:
根据 Fredrick 的评论,我将代码更改为
...
def self.comment_parent
...
但是输出如下:
irb(main):022:0* c=Commontator::Comment
=> Commontator::Comment(id: integer, creator_type: string, creator_id: integer, editor_type: string, editor_id: integer, thread_id: integer, body: text, deleted_at: datetime, cached_votes_up: integer, cached_votes_down:
integer, created_at: datetime, updated_at: datetime)
irb(main):023:0> c.comment_parent
=> "return parent here"
irb(main):024:0> test = c.find(1)
Commontator::Comment Load (35.7ms) SELECT "commontator_comments".* FROM "commontator_comments" WHERE "commontator_comments"."id" = LIMIT 1 [["id", 1]]
=> #<Commontator::Comment id: 1, creator_type: "User", creator_id: 2, editor_type: nil, editor_id: nil, thread_id: 2, body: "Love this parser.", deleted_at: nil, cached_votes_up: 0, cached_votes_down: 0, created_at: "201
5-02-12 22:04:48", updated_at: "2015-02-12 22:04:48">
irb(main):025:0> test.comment_parent
NoMethodError: undefined method `comment_parent' for #<Commontator::Comment:0xad08a10>
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activemodel-4.1.8/lib/active_model/attribute_methods.rb:435:in `method_missing'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.1.8/lib/active_record/attribute_methods.rb:213:in `method_missing'
from (irb):25
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/console.rb:90:in `start'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/console.rb:9:in `start'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/commands_tasks.rb:69:in `console'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands.rb:17:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
根据评论,这是我的解决方案:
总的来说,我希望它作为一个实例方法被调用,所以我的原始代码是正确的。我只是说错了。要调用实例方法,请执行以下操作之一:
Model.new.custom_method
或
my_model = Model.new #or .find(n)
my_model.custom_method
对于我的具体情况,我找到了这个解决方案:
module Commontator
class Comment < ActiveRecord::Base
def comment_parent
# do some magic
thread = Commontator::Thread.find(self.thread_id)
parent_class = thread.commontable_type.camelize.constantize
parent_class.find(thread.commontable_id)
end
end
end
Looking at the library, your parent object has_one :thread, :as => :commontable
, while the thread has_many :comments
.
因此,在 Comment
中,thread.commontable
应该可以让您回到原来的 parent。
我最近才知道猴子补丁这个词,所以我不确定我是否正确。
我正在使用 Commontator gem 在我的博客(Monologue::Post 模型)和我的其他模型上提供评论功能。我 运行 遇到一个问题,我试图从我的评论中获取父对象(即评论的内容)。看起来我必须做三个连接。与其在我的控制器中调用它,我想我可以扩展 gem 的模型以具有一个函数 comment_parent
,该函数 return 父模型。
我有这个:
# config/initializers/comment_model_extenders.rb
module Commontator
class Comment < ActiveRecord::Base
def comment_parent
# do some magic
"return parent here"
end
end
end
我一定是做错了,因为我得到了这个错误:
irb(main):010:0> c=Commontator::Comment
=> Commontator::Comment(id: integer, creator_type: string, creator_id: integer, editor_type: string, editor_id: integer, thread_id: integer, body: text, deleted_at: datetime, cached_votes_up: integer, cached_votes_down:
integer, created_at: datetime, updated_at: datetime)
irb(main):011:0> c.comment_parent
NoMethodError: undefined method `comment_parent' for #<Class:0xab743d0>
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.1.8/lib/active_record/dynamic_matchers.rb:26:in `method_missing'
from (irb):11
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/console.rb:90:in `start'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/console.rb:9:in `start'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/commands_tasks.rb:69:in `console'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands.rb:17:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
编辑:
根据 Fredrick 的评论,我将代码更改为
...
def self.comment_parent
...
但是输出如下:
irb(main):022:0* c=Commontator::Comment
=> Commontator::Comment(id: integer, creator_type: string, creator_id: integer, editor_type: string, editor_id: integer, thread_id: integer, body: text, deleted_at: datetime, cached_votes_up: integer, cached_votes_down:
integer, created_at: datetime, updated_at: datetime)
irb(main):023:0> c.comment_parent
=> "return parent here"
irb(main):024:0> test = c.find(1)
Commontator::Comment Load (35.7ms) SELECT "commontator_comments".* FROM "commontator_comments" WHERE "commontator_comments"."id" = LIMIT 1 [["id", 1]]
=> #<Commontator::Comment id: 1, creator_type: "User", creator_id: 2, editor_type: nil, editor_id: nil, thread_id: 2, body: "Love this parser.", deleted_at: nil, cached_votes_up: 0, cached_votes_down: 0, created_at: "201
5-02-12 22:04:48", updated_at: "2015-02-12 22:04:48">
irb(main):025:0> test.comment_parent
NoMethodError: undefined method `comment_parent' for #<Commontator::Comment:0xad08a10>
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activemodel-4.1.8/lib/active_model/attribute_methods.rb:435:in `method_missing'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.1.8/lib/active_record/attribute_methods.rb:213:in `method_missing'
from (irb):25
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/console.rb:90:in `start'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/console.rb:9:in `start'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/commands_tasks.rb:69:in `console'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.1.8/lib/rails/commands.rb:17:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
根据评论,这是我的解决方案:
总的来说,我希望它作为一个实例方法被调用,所以我的原始代码是正确的。我只是说错了。要调用实例方法,请执行以下操作之一:
Model.new.custom_method
或
my_model = Model.new #or .find(n)
my_model.custom_method
对于我的具体情况,我找到了这个解决方案:
module Commontator
class Comment < ActiveRecord::Base
def comment_parent
# do some magic
thread = Commontator::Thread.find(self.thread_id)
parent_class = thread.commontable_type.camelize.constantize
parent_class.find(thread.commontable_id)
end
end
end
Looking at the library, your parent object has_one :thread, :as => :commontable
, while the thread has_many :comments
.
因此,在 Comment
中,thread.commontable
应该可以让您回到原来的 parent。