I'm pretty new with Ruby on Rails. I have done tutorials and an online class. I know enough to have my way around the development environment, to create tables, controllers, views etc. However, the classes and tutorials don't really show you in depth things you may have to work with in a real software development situation.
I'm in the process of converting a piece of software to the Ruby on Rails platform. Here is the situation. I have a Salesman controller that has salesman information. Then i have a client controller that handles client information. A salesman has many clients and clients have one salesman. I already coded the REST architecture for the Salesman object. Now, i have to create the client. But before i can get to the new action in the controller, i have to select a salesman first. This select salesman page is going to be needed on many other occasions as i will have other controllers such as commissions , purchase orders etc that have to be tied to a salesman first. How do i proceed to code such a "temporary select" page before actually going to the new action in the controller. Can we define custom actions after which i would just redirect_to the new action passing the salesman id as a param?
You need to design the app similar to a multi-tenant app. In your case, Sales Person is like a tenant.
Here is the conceptual design:
add current_id class attribute to SalesMan
cattr_accessor :current_id, instance_writer: false, instance_reader: false
In all your models that belong to a sales person, define the default scope:
default_scope { where(sales_man_id: SalesMan.current_id) }
Ensure that current sales man is set before executing any actions that depend on sales man being pre-selected. There are multiple approaches for achieving this and it also depends what kind of user experience you want to provide. Couple of options:
Only show the navs such as New Client only if a salesman is pre-selected. Provide a menu option to select a salesman. In that action set SalesMan.current_id.
If the salesman is going to be different across many subsequent transactions, you may want to implement a salesman selection (step 1 of workflow) through a controller before action. For example, when user selects New Client nav option, the before action can redirect to sales man selection and set a flag. SalesMan controllers selected action should redirect to New Client action and ensure that proper flags (parameters) are set to avoid cycles. Define a new controller SalesManSelectionController and subclass all the controllers whose models depend on salesman.
I have a table per type structure, I want to write an mvc razor application where my only parameter in the mvc routing is the primary key ID. From there the application will establish which type in my tpt structure the ID belongs to then displays the view formatted for particular type.
In addition, based on the type of the ID the view will also contain information related to that ID in from other tables in the tpt structure.
E.g.
Bob is a person with ID 1234
Entity 1234 has comments in the comments table
Entity 1234 has an entry in the entity relationship table to Simon
I've read a number of articles about making a base class controller, but would my URL change from www.something.burp/1234?
Is it possible to have a set of Index, Edit, Create, Details views that have byType separation?
Just looking for some pointers or ideas for me to research.
Thanks for you help.
MVC4, EF4, C#, SQL 2008
Decided to do multi controller, it's not going to matter to the user if it goes between controllers.
I am trying to come up with a clean design for this -
I am using MVC to process orders, so I have an 'order' entity, with its own controller and views.
From the Create Order view I would like the user to add a 'Customer' entity. I have a controller and CRUD operations for 'customer'.
When someone creates a new Order I would like them to either
1) enter a customer name to see if that customer already exists, and if so, add that Customer to the Order, or
2) Create a new Customer then add that new Customer to the Order.
My problem is I am not sure of a good way to access the Customers from within the Order.
-do I create a partial view for Create Customer, then use that view in the Customer Create AND Order Create?
-then would I create a partial view 'SearchCustomers' that passes params to an action on Customer controller and that returns results? Would I be able to reuse this across the site?
You can see I am not sure about a few things - are partial views the way to reuse things? can partial views be reused across controllers and access different controllers from the ones theyre in?
I have gone through an MVC book and online tutorials but they all seem to use beginner examples, where Model objects don't contain other Model objects.
Thanks for help
Views never "access controllers".
The flow is:
Controller Action Method -> Creates View Model -> Hands it off to a View -> View displays it -> View can pass sub-models on to other partial views
Decomposing everything into smaller models and partial views (or using Editor templates) is a good approach. You can then assemble those smaller models into a larger view model for a complete page, or you can use the ViewBag to assemble them in a non-strongly typed manner.
Trying to figure out the best way to organize a ASP.NET MVC site. Take a very simple 1..N relationship: Company can have many Contacts, Contacts must have exactly one Company.
I have your typical routes:
Company/Index (list all companies)
Company/Details/{int} (details of Company {int})
Company/Create (create new company)
Contact/Index (list all contacts)
Contact/Create (create new contact, company is selected from drop down)
Now if I wanted to create a page that created a Contact in the context of a Company (from the Company detail page) so that the required company is filled in/not editable), what would be the best route of going about that, while not duplicating code where possible.
Not sure if I can leverage the Contact/Create logic/view from the Company controller (and be able to route back to the Company Details page when complete), or mess with the routes to do something like Company/Details/{int}/Contact/Create (not even sure if that makes sense or would work)?
There has got to be a better way then me adding my logic and view for adding a Contact into my Controller view and having it duplicated.
Cant find the link, but found some information about using named routes to help out :)
In the current examples on ASP.NET MVC I see quite basic entities, with simple CRUD methods.
But I'm not sure about what to do with more advanced models. Let me give an example:
We have a garage website. The garage has:
Inventory with carparts
Employees
Customers
Cars that consists of all cars that are/were in the garage
Now lets take the car, the car might have a collection of employees that worked on the car (derived from the original employee class, adds some extra props that tie him to the car), a collection of carparts that have been replaced (also derived, adds for example SerialNr, and ReplacementDate prop) , and of course a customer prop of the customer whoe owns the car.
Now in rest I would like to see the following:
/cars/423 [get] //show car # 423
/cars/423/edit [get] //shows the edit form (ajax enabled, so also shows the other props)
/cars/423/carparts [get] //gets the carparts inside the car
/cars/423/carparts/32/edit [post] //updates that specific carpart inside the specific car
/cars/423/employees [get] //gets the employees who worked on the car
/inventory [get]
/inventory/1234/edit [get] //gets the update form for carpart with ID 1234
/employees [get] //gets all the employees in the company
So how would I build my Controllers? Should I add all those CRUD methods for the child elements inside the CarsController? Doesn't that make a very fat controller because of the tens of methods (this model is overly simplified, the car has many more parent-child relationships)? Or should I create a EmployeesInCar controller (seems bad)...
Thanks a lot.
EDIT:
First of all the example is hypothetical only, just an example.
If I follow the suggestion I would have a CarController which only handles cars. And my PartsController would handle only Parts. But we have two sets of Parts, a general one (for the inventory); and we have a Part inside a car, which derives from the general one, but adds properties such as SerialNumber and ReplacementDate.
So my Parts controller becomes quite fat, for the example let's call the entities: GeneralPart (in inventory) and SpecificPart (the derived class, with the extra properties)
Index -> Returns all GeneralParts in inventory.
IndexByCar(int id) -> Return all SpecificParts by Car.
etc. etc.
Because each action deals with either a General Part or a Specific Part. The same is for employees, we have the base employee class, and a specific one, with extra properties.
If you wish to use the kinds of paths you provided in your example, then it sounds like you should learn how to use the Routing engine in .NET 3.5. You should be able to use the kinds of urls you need, but you will need to create several custom routes and probably a custom route handler to accomplish it. The Routing engine in .NET 3.5 is very flexible and was not designed specifically for MVC...its actually very generic and can provide a very broad, probably unlimited range of url rewriting.
Its a bit late where I live, so the example I was trying to write just isn't forming. :P Suffice to say, a custom route handler and some new route mappings should get you where you need to be.
EDIT: This may be of help:
http://codingcockerel.co.uk/2008/05/26/custom-routing-for-asp-net-mvc/
EDIT 2:
I left out controllers before. The routing just gets you the ability to use the kinds of URLs you want. And thats a good thing...the kinds of URL's you proposed will provide a better SEO experience long-term. As for organizing your controllers, I recommend keeping it simple:
/Controllers/CarsController.cs
/Controllers/PartsController.cs
/Controllers/EmployeesController.cs
/Controllers/InventoryController.cs
Your routes would match your url patterns, and turn them into a proper route to your controller, taking the ID's and matching them to the parameters of your actions.
EDIT 3:
So, now that I understand your question more fully, I hope I can answer it better. Generally speaking, I think controllers should map 1:1 with your entities. If you have a GeneralPart, then you should have a controller dedicated to managing general parts. If you have CarPart, then you should have a controller dedicated to managing car parts. If CarParts are GeneralParts, and they can behave like GeneralParts in some cases, then it is probably best to have those management aspects on the GeneralPartsController, unless that management deals with any special attributes of a CarPart...in which case management should be delegated to CarPartsController. It is kind of elegant how polymorphism plays into controller organization, and how the "is a" relationship allows you to reuse controllers to manage multiple types.
To be honest, you have a fairly complex scenario I havn't directly encountered in my time working with ASP.NET MVC. I try to avoid such scenarios as much as possible, because they give rise to complicated questions like this that tend to be subjective in their answers. Ultimately, you should organize your controllers in a way that makes logical sense to how they are used, how they map to your entities, and how well they organize the behavior you are interested in exposing. Sometimes, it isn't logical to map all of your controllers to a single entity. Sometimes you need to have a "composite" controller that deals with actions that operate on multiple entities at once, or graphs of entities. In these cases, its probably best to have controllers dedicated to those particular behavioral groups, rather than trying to find one entity-specific controller that "sorta fits".
Your design should initially focus on the entities. You have car, employees and inventory. Write a controller for each one of these. That will give you the basic routes:
/cars/{action}/{id}
/employees/{action}/{id}
/inventory/{action}/{id}
From here you should be able to write a new route with a custom route constraint with the following structure:
/cars/{id}/part/{id}/
This is also slightly better than /cars/{id}/carpart/{id} because the word car in carpart is redundant. /car/.../part/ indicates that part is for a car.
Thinking about things like these for URI design is really important early on because changing the URI design later will break search engine indices, bookmarks and links.
Your "CarPart" entity (class CarPartModel) can be in "stock" state (class StockCarPartModel : CarPartModel) or "replaced" state (class ReplacedCarPartModel : CarPartModel). Then:
GET to /carpart/index should return all entities (CarPartModel)
GET to /carpart/replaced should return replaced parts (ReplacedCarPartModel)
GET to /carpart/bycar/{id} should return parts, related to specific car (ReplacedCarPartModel)
GET to /carpart/inventory should return parts in stock (StockCarPartModel)
This all is handled by "Default" route and in your CarPartController your have actions:
public ActionResult Index() { ... }
public ActionResult Replaced() { ... }
public ActionResult ByCar(string carId) { ... }
public ActionResult Inventory() { ... }
I think your controller is not fat. It is normal for controller to deal with Model inheritance. The main complexity will be in your ViewModels and Views
You don't need to have too many things going on in a controller.
Think of a controller as a class that determines what the user wants and what it should see in the end.
What user wants is determined by the ASP.NET MVC engine automatically for you, with the help of the routes you defined in the Global.asax file. Then the controller should decide what view the user should see as a result of the request he/she made.
So for your application things would go something like this :
Global.asax
routes.MapRoute("Cars", "cars/{id}/{action}",
new { controller = "Cars", action = "Details", id = "" } );
//This route should give you the URLs you listed on your question
CarsController.cs
public class CarsController : Controller {
//this action will be called for URLs like "/cars/423"
//or /cars/423/details
public ActionResult Details(int id) {
//You would most likely have a service or business logic layer
//which handles talking to your DAL and returning the objects
//that are needed for presentation and likes
Car car = SomeClass.GetCar(id);
if (car == null) {
//if there's no car with the ID specified in the URL
//then show a view explaining that
return View("CarNotFound");
}
//if there's a car with that ID then return a view that
//takes Car as its model and shows details about it
return View(car);
}
//this action will be called for URLs like /cars/423/edit
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Edit(int id) {
//again get the car, show an edit form if it's available for editing
}
//this action will be called for URLs like /cars/423/edit too
//but only when the request verb is POST
[AcceptVerbs(HttpVerbs.Post), ActionName("Edit")]
public ActionResult Save(int id) {
//save the changes on the car, again using your business logic layer
//you don't need the actual implementation of saving the car here
//then either show a confirmation message with a view,
//saying the car was saved or redirect the user to the
//Details action with the id of the car they just edited
}
}
So basically this is how you would set up your controller(s) for an application like that.
I would recommend using Restful Routing for ASP .NET MVC:
https://github.com/stevehodgkiss/restful-routing