While I do find that the PHP Symfony framework is wonderful for many things, I am finding it difficult to create easily scalable dynamic menus for a website.
I am wondering how other Symfony developers out there have dealt with this issue.
I will give a simple example as to what I am asking.
If go to www.fool.com you will see that they have a typical menu setup. A list of categories with one of them being the active one that is in some way highlighted with CSS.
What would be a good way to make this dynamically created in a Symfony project. Passing variables of some sort from module to module. I have not yet found an elegant solution.
Generally, I just manually build an array of module/action combinations that I'd like to appear in my menu. It'd be fairly easy to grab this information from a dynamic source (like a configuration file, or a database):
$this->menu = array(
'Home' => array('default', 'index'),
'About Us' => array('default', 'aboutUs'),
'Products' => array('products', 'index')
);
Then, I use the controller's getActionName and getMethodName methods to determine which item in my menu is the current one:
$this->current = array_search(array($this->getModuleName(), $this->getActionName()), $this->menu);
Then I can iterate over $menu, from within the template, to build up the menu. And I can compare the items with $current, to determine whether I should set a "current" class on the menu item's <li>.
The fool.com example you give is a bit more complicated, because it's two level. In that case, you'd probably want to be generating your menu tree from a database, perhaps making use of Propel's nested set support.
Related
I have a model Navigation that has a polymorphic target. That target can be a Page, an ExternalLink, or a Plugin. Each of these targets has different attributes (page has content, title, external link has title, url, plugin has its own polymorphic relations.
I'm building a little form to add a Navigation link, and I want to give my users the option to select an existing one of these relations (which is easy enough, just a grouped collection select), but I also would like to let them select a 'New' option for each of these target models.
The question is -- how do I include it in the same form?
I could make a form object, but that feels like the last-resort option. I know I can accept nested attributes for target, but I don't know how to do that with a selection form as well. I know I could do some js hackery to add or remove form elements on selecting or not selecting the 'new' options.
All of these don't feel railsey. This problem feels like a not-uncommon issue, and I imagine this is a solved problem that I'm trying to reinvent the wheel for. What option am I missing? What is the rails way to make this?
You may want to look at the Cocoon gem, will handle a lot of the "js hackery" you alluded to.
This post shows how to use Cocoon to render the appropriate fields for (in your case) each of the possible target classes.
Whether you have a separate button for each target class is up to you.
I think you should use globalid gem for this.
Here is a good article describing how it works.
GlobalID helps you uniquely identify your models. E.g. gid://Company/1 and gid://Employee/1 has the same IDs, but different GlobalIDs. You can actually find model simply by using GlobalID::Locator:
GlobalID::Locator.locate gid_value
This should make simple combo-boxes easily programmable.
I have strange question. I want in my helper to have array of paths that are available for specific resource.For example, if we have a model Comment I want to have an array which will have the following elements: [new_comment_path, comments_path] etc. Is this possible to do?
Edit:
I build left side menu in rails. It will work like tree menu. I don't want to use external plugins. Only thing that i must do is to have a all paths for my models.
You can do
Rails.application.routes.routes.map{|x| x.name}.reject{|x| x.blank?}
Which will get all named routes. I'm not sure if there is a way of just getting routes for one resource though
I am fairly new to Umbraco and I am wondering where I should put pieces of random data.
I have a lot of experience with Sitecore, used it for several years, I am certified etc etc. But now I have to build something with Umbraco. At a first glance Umbraco looks inferior to Sitecore in every way, but I might be wrong about that.
So what I am wondering is, where should I put non-browsable pieces of data that are visible on several places throughout the website? I'd like to create data items in Umbraco for things like Testimonials, Offices? I'd like to have a centralized place in Umbraco where they can be maintained and reference them from a page node. But the way it looks now is that everything has to be on the page node. Which is sort ok, for your average family webpage.
Could someone please shed some light on this?
You could create another node under the man content and call it site settings and store them there that way all pages under the home page are just visible pages on the front end and all data nodes are in a separate area.
There is one property in umbraco that you can add to document types and name it "umbracoNaviHide" (for alias, the name can be anything). This allows wires in automatically to the .IsVisible() method.
var children = Model.Content.Children.Where(x => x.IsVisible());
I find this situation to be very frequent, think of slideshows. When I make an Umbraco website, under my root node I normalle havea Slideshow document type (that contains slides) and I programmatically traverse those to build the slideshow on the home page for example. This Slideshow document has that "umbracoNaviHide" property and I skip it from my menus either using the .IsVisible() method or by manually skipping specific document types.
var menuItems = Model.Content.Children.Where(x => x.DocumentTypeAlias != "Slideshow" && x.DocumentTypeAlias != "Search");
On the other hand, if you are looking for "labels", you can look at "Dictionnary" items under the "Settings" tab.
To directly answer your questions, I reccomend putting non-browsable pieces of data as children of the relevant browsable content node. (But there are other valid ways to do this, it really is up to you and what's best for your content editors.)
Hope this helps.
I have a very simple Rails application that performs regular CRUD operations on an object (Path), this all fits nicely in the REST philosophy of Rails. Now however, I need to add a "Duplicate" feature (i.e. create new path from existing path). I have added it as an (RESTfull) action in my path_controller, so far so good (maybe not completely in line with the REST philosophy but I am not a purist).
Now I want to extend the functionality so that the users can choose to either create a completely new path from an existing one or copy the existing path to another, already existing path (duplicating its children). This means I am going to need a few extra Views:
one that allows them to pick Option 1 (Create New Object) or Option 2 (Duplicate to existing Object).
If they choose Option 2, I need another View that lets them then pick the path they want to copy to.
Each of these views needs a corresponding action, and it is here that I am struggling as to where this all fits in REST.
This is a fairly simple example but as my UIs get more complex, I always run into this issue: How do I make my actions I need for my UI fit in REST controllers?
Just add a new collection route to your resource:
resources :paths do
collection do
get :duplicate
end
end
and add a duplicate method to your paths controller and views for it...
now you can access and address specifi routes for your users choice.
I am in the process of building a super simple CMS to handle smaller "static" page type projects (e.g. - small sites for friends). I have different "page types" that I would like to add. I built something similar in Coldfusion previously. Looked something like this:
table content_type:
content_type_code varchar(10)
content_type_name
table content:
content_id
content_type_code varchar(10)
content_name
content_desc
content_url
I would create a content type called "blog" or "photo" and each time a content was added, it'd get assigned the content_type_code. Then in /blog/ I'd query for all content that had a content_type_code of "blog".
Now that I'm using Ruby/RoR I am trying to think about things differently. I was thinking a better way might be to use nested pages with awesome_nested_set (https://github.com/collectiveidea/awesome_nested_set). But I'm not sure if that's the best solution.
Then I could create a page called "blog" and add to that many pages. So essentially the top level would take place of the "content_type" from my previous example.
Can someone steer me in the right direction on what the best method would be? I'm a newb looking for a kick in the right direction.
EDIT
I should add that the only real thing that I would change between the different "types" of content would be the layout and where they are displayed ("photo" content at /photos/, "blog" content at /blog/).
I try to recap:
You want to build a CMS
Your CMS manages a single web site
A web site is made of content
There are differenti type of contents, and I am assuming every type of content has its own behaviour
Contents are organized in a tree
Here is the plan I suggest you:
Create the Content resource; use the scaffold to have something already working, adding few field (title and body in example)
Add validations to your new model
Write a couple of unit tests against your validation (quite useless, just to see how it works)
Install awesome_nested_set and manage to make it working with your model
Work on the UI to make it quite easy to create new content, move content around, edit a single content
Now its time to implement the content types; STI is the Rails way, but I have to warn you it can be really hard. I suggest you to reiterate 1, 2, 3, 5 to create new models for Photo and BlogPost
Once you will be there, you will have hundreds of ideas to implement. Have fun :)
Instead of using content_type I would rather let the user choose a model on a selection page, like "photo" or "blog" and load an editing page based on that selection. So the user wants a new 'blog'-entry they get redirected to blog/new or 'photo' for photo/new. It's the easiest way to go in terms of usability and your controlling backend and you don't have redundant data (for example an empty photo url which is not necessary in a blog-type) in your database.