AnA*_*ice 58 ruby ruby-on-rails ruby-on-rails-3
在我的模型中,我有:
after_create :push_create
Run Code Online (Sandbox Code Playgroud)
我push_create我需要渲染一个视图.我试着这样做:
def push_event(event_type)
X["XXXXX-#{Rails.env}"].trigger(event_type,
{
:content => render( :partial =>"feeds/feed_item", :locals => { :feed_item => self })
}
)
end
Run Code Online (Sandbox Code Playgroud)
这会激怒rails,因为它不像我在模型中渲染视图但我需要它.
错误:
NoMethodError (undefined method `render' for #<WallFeed:0x1039be070>):
Run Code Online (Sandbox Code Playgroud)
建议?我应该以某种方式在其他地方呈现它吗?或者我如何在模型中渲染以设置内容?谢谢
ste*_*com 65
好吧,"他们"是对的.你真的必须在控制器中进行渲染 - 但从模型中调用该控制器是公平的游戏!幸运的是,Rails 3中的AbstractController比我想象的要容易.我结束了制作一个简单的ActionPusher类,就像ActionMailer一样.也许有一天我会雄心勃勃,让它成为一个合适的宝石,但这应该成为我鞋子里的其他人的良好开端.
我从这个链接获得了最多的帮助:http://www.amberbit.com/blog/2011/12/27/render-views-and-partials-outside-controllers-in-rails-3/
在lib/action_pusher.rb中
class ActionPusher < AbstractController::Base
include AbstractController::Rendering
include AbstractController::Helpers
include AbstractController::Translation
include AbstractController::AssetPaths
include Rails.application.routes.url_helpers
helper ApplicationHelper
self.view_paths = "app/views"
class Pushable
def initialize(channel, pushtext)
@channel = channel
@pushtext = pushtext
end
def push
Pusher[@channel].trigger('rjs_push', @pushtext )
end
end
end
Run Code Online (Sandbox Code Playgroud)
在app/pushers/users_pusher.rb中.我猜这个要求可能会更加全球化吗?
require 'action_pusher'
class UsersPusher < ActionPusher
def initialize(user)
@user = user
end
def channel
@user.pusher_key
end
def add_notice(notice = nil)
@notice = notice
Pushable.new channel, render(template: 'users_pusher/add_notice')
end
end
Run Code Online (Sandbox Code Playgroud)
现在在我的模型中,我可以这样做:
after_commit :push_add_notice
private
def push_add_notice
UsersPusher.new(user).add_notice(self).push
end
Run Code Online (Sandbox Code Playgroud)
然后你会想要一个部分的,例如app/views/users_pusher/add_notice.js.haml,它可以很简单:
alert('#{@notice.body}')
Run Code Online (Sandbox Code Playgroud)
我猜你真的不需要在最后使用Pushable内部类和.push调用,但我想让它看起来像ActiveMailer.我的用户模型上也有一个pusher_key方法,为每个用户创建一个频道 - 但这是我第一天有像Pusher这样的东西,所以我不能肯定这是否是正确的策略.还有更多可以充实,但这足以让我开始.
祝好运!
我已经得到了解决方案的大致轮廓.像这样,在你的模型中:
after_create :push_new_message
private
def render_anywhere(partial, assigns = {})
view = ActionView::Base.new(ActionController::Base.view_paths, assigns)
view.extend ApplicationHelper
view.render(:partial => partial)
end
def push_new_message
pushstring = render_anywhere('notices/push_new_message', :message_text => self.body)
Pusher[user.pusher_key].trigger!('new_message', pushstring)
end
Run Code Online (Sandbox Code Playgroud)
这肯定是有效的 - 模板正在渲染,并在客户端成功获得eval().我打算清理它,几乎可以肯定地将render_anywhere移动到某个更普遍的地方,并且可能尝试类似这样的东西
我可以看到推送将需要他们自己的模板,调用普遍可用的模板,我可能会尝试在一个地方收集它们.一个不错的小问题是我有时会在部分中使用controller_name,比如点亮一个菜单项,但我显然必须采取不同的策略.我猜我可能要做些什么来获得更多帮助,但我还没有到达那里.
成功!万岁!这应该回答你的问题,我的 - 如果以后看起来合适,我会添加更多细节.祝好运!!!!
我没有答案,但这个及时的问题值得进一步澄清,我希望通过帮助问:) 来接近我的答案:)
我面临着同样的问题.为了更清楚地解释一下,Pusher异步将内容发送到连接的用户浏览器.典型的用例是向用户显示他们有来自其他用户的新消息.使用Pusher,您可以将消息发送到接收者的浏览器,以便他们在登录时立即得到通知.有关Pusher可以做的非常棒的演示,请查看http://wordsquared.com/
您可以发送您喜欢的任何数据,例如JSON哈希来解释您的喜好,但发送RJS非常方便,就像在客户端使用任何其他ajax调用和eval()一样.这样,您可以(例如)渲染菜单栏的模板,完整地更新它,或者仅显示给用户的新消息计数,使用所有相同的部分来保持其骨干.原则上,你可以从发送者的控制器渲染部分,但这也没有多大意义,甚至可能没有请求,它可能由cron作业触发,例如,或某些其他事件,如股价变动.发送者控制器不应该知道它 - 我喜欢让我的控制器处于饥饿状态;)
这可能听起来像是违反了MVC,但实际上并非如此 - 它确实应该通过ActionMailer之类的东西来解决,但是与应用程序的其余部分共享帮助程序和部分内容.我知道在我的应用程序中,我想在(或代替)ActionMailer调用的同时发送Pusher事件.我想基于来自用户A的事件为用户B呈现任意部分.
这些链接可能指向解决方案:
最后一个看起来最有希望,提供这个诱人的片段:
def render_anywhere(partial, assigns)
view = ActionView::Base.new(Rails::Configuration.new.view_path, assigns)
ActionView::Base.helper_modules.each { |helper| view.extend helper }
view.extend ApplicationHelper
view.render(:partial => partial)
end
Run Code Online (Sandbox Code Playgroud)
正如上面另一张海报提供的链接一样.
如果我得到了一些工作,我会报告回来
tl;博士:我也是!
Kev*_*vin 58
我这样做:
ApplicationController.new.render_to_string(partial: 'messages/any', locals: { variable: 'value' })
Run Code Online (Sandbox Code Playgroud)
Ole*_*yev 35
在Rails 5中,由于实现了控制器类方法,在控制器外部呈现变得非常简单: render
# render template
ApplicationController.render 'templates/name'
# render action
FooController.render :index
# render file
ApplicationController.render file: 'path'
# render inline
ApplicationController.render inline: 'erb content'
Run Code Online (Sandbox Code Playgroud)
在render控制器外部调用时,可以通过assigns选项分配实例变量,并使用控制器中可用的任何其他选项:
ApplicationController.render(
assigns: { article: Article.take },
template: 'articles/show',
layout: false
)
Run Code Online (Sandbox Code Playgroud)
可以通过默认选项来定制请求环境
ApplicationController.render inline: '<%= users_url %>'
# => 'http://default_host.com/users'
ApplicationController.renderer.defaults[:http_host] = 'custom_host.org'
# => "custom_host.org"
ApplicationController.render inline: '<%= users_url %>'
# => 'http://custom_host.org/users'
Run Code Online (Sandbox Code Playgroud)
或者通过初始化一个新的渲染器显式地
renderer = ApplicationController.renderer.new(
http_host: 'custom_host.org',
https: true
)
renderer.render inline: '<%= users_url %>'
# => 'https://custom_host.org/users'
Run Code Online (Sandbox Code Playgroud)
希望有所帮助.
hsg*_*ert 24
您可以直接使用ActionView并将部分渲染为字符串而无需控制器.我发现该模式对于创建封装一些javascript生成的模型很有用.
html = ActionView::Base.new(Rails.configuration.paths['app/views']).render(
partial: 'test',
formats: [:html],
handlers: [:erb],
locals: { variable: 'value' }
)
Run Code Online (Sandbox Code Playgroud)
然后,只需将您_test.html.erb的视图文件夹放入其中即可试用!
Rails 6.0.0 兼容答案,因为我在搜索解决方案时最终出现在此页面上:
lookup_context = ActionView::LookupContext.new(Rails.configuration.paths["app/views"])
renderer = ActionView::Base.new(lookup_context)
renderer.extend(Rails.application.helpers)
renderer.render \
template: "foo/bar",
formats: [:html],
handlers: [:erb],
locals: { user: User.new }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
40156 次 |
| 最近记录: |