2017-09-09 45 views
0

我需要处理一个特殊的情况,即使用从非持久数据构造的URL来生成电子邮件视图。Rails强制to_param返回一些东西,即使没有持久

示例:假设我的用户可以创建帖子,并且触发了创建帖子的通知电子邮件,我想向用户发送虚假帖子创建的示例。对于这一点,我使用的是FactoryGirl.build(:post)并通过这个我PostMailer.notify_of_creation(@post)

在日常的Rails的生活中,我们通过传递作为参数模型本身使用的路线url_helpers和路线产生将模型自动转换成其ID是用于路径URL生成(在article_path(@article),路线帮手转换@article@article.id为构建/articles/:id URL。

我相信这是在ActiveRecord的是相同的,但反正在Mongoid,如果模型没有坚持这个转换失败(这有点不错,因为它可以防止生成可能与实际数据不一致的URL)

所以在我的特定情况下,URL生成的崩溃,并将该模型是不持久:

<%= post_url(@post_not_persisted) %> 

崩溃,并

ActionView::Template::Error: No route matches {:action=>"show", :controller=>"posts", :post_id=>#<Post _id: 59b3ea2aaba9cf202d4eecb6 ...

有没有一种方法可以让我搭桥这种限制只在一个非常具体的范围内?否则,我可以通过resource_path(@model.id.to_s)或更好@model.class.name更换所有我resource_path(@model)但这并不觉得自己是正确的情况下...

编辑:

的主要问题是

Foo.new.to_param # => nil 
# whereas 
Foo.new.id.to_s # => "59b528e8aba9cf74ce5d06c0" 

我需要给力to_param返回ID(或其他东西),即使模型没有持久。现在,我在看的改进,看看我是否可以使用范围的猴补丁,但如果你有更好的想法,请用我的细化当是我的客人:-)

module ForceToParamToUseIdRefinement 
    refine Foo do 
    def to_param 
     self.class.name + 'ID' 
    end 
    end 
end 

但是我似乎有一个小范围的问题,因为这不会像url_helpers那样冒泡。当在控制台中使用te精化时它工作正常(Foo.new.to_param # => 59b528e8aba9cf74ce5d06c0

回答

0

我找到了一种使用动态方法覆盖的方法。我不太喜欢它,但它完成了工作。我基本上是对我在测试中使用的实例进行monkeypatatching。

为了方便,我创建了一个类的方法example_model_accessor,基本上表现得像attr_accessor节选了二传手补丁对象

def example_model_accessor(model_name) 
    attr_reader model_name 

    define_method(:"#{model_name}=") do |instance| 
    def instance.to_param 
     self.class.name + 'ID' 
    end 
    instance_variable_set(:"@#{model_name}", instance) 
    end 
end 

的#to_param方法然后在我的代码,我可以只使用

class Testing 
    example_model_accessor :message 

    def generate_view_with_unpersisted_data 
    self.message = FactoryGirl.build(:message) 
    MessageMailer.created(message).deliver_now 
    end 
end 

# views/message_mailer/created.html.erb 
... 
<%= message_path(@message) %> <!-- Will work now and output "/messages/MessageID" ! --> 
相关问题