public override void init(RuntimeServices rs, InternalContextAdapter context, INode node) { base.init(rs, context, node); INode compNameNode = node.jjtGetChild(0); if (compNameNode == null) { String message = String.Format("You must specify the component name on the #component directive"); throw new RailsException(message); } componentName = compNameNode.FirstToken.image; if (componentName == null) { String message = String.Format("Could not obtain component name from the #component directive"); throw new RailsException(message); } component = viewComponentFactory.Create(componentName); }
public override bool Render(IInternalContextAdapter context, TextWriter writer, INode node) { var railsContext = EngineContextLocator.Instance.LocateCurrentContext(); var registry = railsContext.Services.GetService <IViewComponentFactory>().Registry; var viewDescProvider = railsContext.Services.GetService <IViewComponentDescriptorProvider>(); var cacheProvider = railsContext.Services.CacheProvider; var compNameNode = node.GetChild(0); if (compNameNode == null) { var message = String.Format("You must specify the component name on the #{0} directive", Name); throw new ViewComponentException(message); } var componentName = compNameNode.FirstToken.Image; if (componentName == null) { var message = String.Format("Could not obtain component name from the #{0} directive", Name); throw new ViewComponentException(message); } if (componentName.StartsWith("$")) { var nodeContent = compNameNode.Literal.Trim('"', '\''); var inlineNode = runtimeServices.Parse(new StringReader(nodeContent), context.CurrentTemplateName, false); inlineNode.Init(context, runtimeServices); componentName = (string)Evaluate(inlineNode, context); } var componentParams = CreateParameters(context, node); var viewComptype = registry.GetViewComponent(componentName); ViewComponentDescriptor descriptor = null; CacheKey key = null; if (viewComptype != null) { descriptor = viewDescProvider.Collect(viewComptype); } var isOutputtingToCache = false; ViewComponentCacheBag bag = null; if (descriptor != null && descriptor.IsCacheable) { key = descriptor.CacheKeyGenerator.Create(componentName, componentParams, railsContext); if (key != null) { var cachedContent = (ViewComponentCacheBag)cacheProvider.Get(key.ToString()); if (cachedContent != null) { // Restore entries foreach (var pair in cachedContent.ContextEntries) { context[pair.Key] = pair.Value; } // Render from cache writer.Write(cachedContent.Content); return(true); } isOutputtingToCache = true; bag = new ViewComponentCacheBag(); } } var component = viewComponentFactory.Create(componentName); if (component == null) { throw new MonoRailException("ViewComponentFactory returned a null ViewComponent for " + componentName + ". " + "Please investigate the implementation: " + viewComponentFactory.GetType().FullName); } try { var directiveNode = (ASTDirective)node; var renderer = (IViewRenderer)directiveNode.Directive; var contextAdapter = new NVelocityViewContextAdapter(componentName, node, viewEngine, renderer) { Context = isOutputtingToCache ? new CacheAwareContext(context, bag) : context }; INode bodyNode = null; if (node.ChildrenCount > 0) { bodyNode = node.GetChild(node.ChildrenCount - 1); } var output = isOutputtingToCache ? bag.CacheWriter : writer; contextAdapter.BodyNode = bodyNode; contextAdapter.ComponentParams = componentParams; contextAdapter.TextWriter = output; component.Init(railsContext, contextAdapter); ProcessSubSections(component, contextAdapter); const string ViewComponentContextKey = "viewcomponent"; var previousComp = context[ViewComponentContextKey]; try { context[ViewComponentContextKey] = component; component.Render(); if (contextAdapter.ViewToRender != null) { RenderComponentView(context, contextAdapter.ViewToRender, output, contextAdapter); } if (isOutputtingToCache) { // Save output cacheProvider.Store(key.ToString(), bag); // Output to correct writer writer.Write(bag.Content); } } finally { if (previousComp != null) { context[ViewComponentContextKey] = previousComp; } else { context.Remove(ViewComponentContextKey); } } } finally { viewComponentFactory.Release(component); } return(true); }