Incrementing an index on a has_many dependent resource - ruby-on-rails

I have an project with many Books. Each book has many Pages. I would like each page to have a pageIndex that makes it unique in relation to the book, so that each time I build a page through the book this index is incremented. Obviously all models have their own id, but that id is unique across all Pages. I would like the first Page built by a Book to have a a pageIndex of 0, the second to have a pageIndex of 1, the third; 2 etc.
I could do something like this:
book = User.books.last
pageIndex = book.pages.count
book.pages.create(:pageIndex => pageIndex)
But it seems to me that it would be much nicer if this index was set automatically by the book when it created a dependant resource of type Page. Is there a way of doing this?
Please note that I have seen this question but what I am looking for is a hook in the parent/owning Resource that allows me to do something to the dependant resource it has created after it has created it and before it saves it. Something like the before_save callback but related to creation of a dependent resource: after_dependent_create.

Associations also have some callbacks. See here http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html "Association callbacks". Possible callbacks are: before_add, after_add, before_remove and after_remove.
Also I would add a counter_cache on the book so you'll know how many pages you have and when creating a new page you won't have to count the existing pages

Related

Ruby on Rails - Re-usable Select item page

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.

Ruby On Rails Model/Controller Question

I have a CourseCategory model and a Course Model along with corresponding controllers course_categories and courses. A course belongs to a category and a category has many courses.
I want to have a page that shows courses in a particular category. Which controller does this function belong in? Should I nest these resources? Just looking for the best way to model this.
CourseCategories. Think of your URLs, thats the easiest way to make a decision like this:
example.com/course_categories/1
--or, better, use slugs for categories instead of ids and you'd get--
example.com/course_categories/awesome_courses/
However, it might be worthwhile to consider simple having a "categories" model rather than a "course_categories" model. Then you could nest categories under courses, and you'd get something like:
example.com/courses/categories/1 or example.com/courses/categories/hard
I would say you are going to be displaying a coursecategory listing - therefore would belong in the coursecategory controller.
You can add this so the courses controller and take a parameter saying which category to respond with.
Or, if it makes sense, you can make courses a nested attributed of course_categories. Then this will be the default behavior.
EDIT Since I gave the opposite answer of someone else. The first suggestion would let you
/courses?course_category=math
or
/courses/math
Then look for the course_category in the controller
The second idea would let you do
/math/courses
An alternative would be to do something like
routes.rb
resources :course_catgeories do
resources :courses
end
courses_controller.rb
def index
#course_category = CourseCategory.find(params[:course_category_id])
#courses = #course_category.courses
end
The logic here being, if you're listing courses for a category, then the conventional action for that is the index action. Except in this case, you're scoping the listing to a particular category. So if you think about it in those terms, I think this approach better models your domain.
This approach effectively produces the following routes:
/course_categories/ (category index page)
/course_categories/1 (category show page)
/course_categories/1/courses (course index page)
/course_categories/1/courses/1 (course show page)

ASP.NET MVC 2 Controllers to Model Associations

In my model I have relationships like this:
[Person]
PersonId (PK)
...
[Orders]
OrderId (PK)
PersonId (FK to Person.PersonId)
...
A person can have multiple orders.
I generated PersonController with Create/Details/List/Edit views. I want to be able to manipulate Orders also, but within the context of a Person. In other words, I'd like the workflow to be
User browses a list of people (/Persons)
User selects 'View Orders' link next to a specific Person (/Persons/4/Orders/)
User sees a list of orders with Create/Details/Edit as well (/Persons/4/Orders/Edit/38)
Is this the right way to set up my controllers/routes?
Should I just access orders at routes like (/Orders/Edit/38) instead?
Right now I have:
PersonController
OrderController
Should I create a PersonOrderController or can I achieve what I want using only the two controllers I already have?
You should probably use just the two Controllers you already have. It is a judgment call however. Two different excellent MVC designers might do this two different ways. Unless you already see a lot of other work for your OrderController, you should start with two controllers. If OrderController becomes bloated, you can refactor.

asp.net mvc session?

Im building an admin interface for a medical records management app.
My client has asked me for a way to easily select the patient the user wants to work with without having to select the patient everytime he wants to perform an action.
So, say for instance he wants to store a record for the patient's current status (weight, size, etc) and then assign the same patient to a different doctor or change the company the patient currently works for.. he doesnt want to select the same patient all three times... he wants a select dropdown for patients and perform the different actions for that patient.
Im thinking this should be somehow stored in a session variable.. I have a table of patients and Im using LinqtoSql classes.... what do you reccommend?? help please.
Sounds like you want to put something into Session--perhaps some of the basic "recent patient" information, such as a patient ID, patient name, etc.
Definitely take a look at this post on how to do it in a very graceful way.
You could use the session to keep a list of recently active patient records for a given users session. Every time the user selects a new patient simply add that patient's name to the "Recent" list. Since you can control the length of the session you could just allow the list to expire when the user's session does. As far as not making the user select a customer again, just have it auto-select the most recent (last entry) on the list of recent customers.
Personally I would consider caching as an option here. By the sounds of it you want to load ALL data for ALL patients which is fine for a small amount of data but will not scale gracefully.
Consider going to the database the FIRST time you need the patient's data, and getting your data from the cache for subsequent queries...
The best way is to have the id in the route.
Use something like this when registering routes:
routes.MapRoute(
"Standard",
"{controller}/{action}/{PatientId}",
new
{
controller = "home",
action = "index",
PatientId = ""
}
);
When you select a Patient you post to an action that sets the PatientID in the RouteParameterCollection and redirect to the the action that displays the form for changing the patient. this way you always have the patientID in the URL.
Using session has some drawbacks:
If you have 2 windows open both use
the same session. This might confuse
users.
You can not bookmark a page
Session is usually stored in memory
on the appserver. This might lead to
performance problems if extensively used.

Showing 1:N and M:N relationships with Symfony 1.2.9 admin generator

I am using Symfony 1.2.9 (with Propel ORM) to create a website. I have started using the admin generator to implement the admin functionality. I am having all manner of problems getting the admin manager to display an object (blog) that has one 1:N relation (blogposts) and one N:M relationship (blogroll).
This is proving to be far more difficult than I had ever imagined (and I daresay, than it needs to be). I have already spent two days on this problem and have not made much progress. I am trying to generate admin functionality for a blog.
I have posted an abridged version of my schema here. Hopefully it will help clarify the problem I am having (maybe I am not explaining the problem clearly enough - but hopefully, the schema should clarify the problem I am facing, and what I'm trying to do).
A blog has 0 to 1 blog rolls, 0 to N blog posts attached to it. Each blog post has 0 to M comments attached to it. Currently, I can view a list of blogs. But I want to add 2 interactions (or links) that can make me:
view the blogroll (which is a list of blogs attached to the blog)
view the list of blogposts attached to a blog.
When a blogpost list is shown, I want link to show a link (same functionality as before), that allows me to show the list of comments for the selected blogpost.
I am sure I am not the first (or only) person that has tried to do this before. Am I going about it the wrong way, is there a better (i.e. more intuitie for the user) way of displaying and performing CRUD on objects with such relationships?. Can anyone out there help?
Why don't you do it as you have proposed by yourself in your other question.
(This is again for Doctrine but for Propel it should be similar).
Create an object action in your generator.yml:
list:
object_actions:
bloglist: {label: Bloglist}
Then in your actions.class.php you have to add a function:
public function executeListBloglist(sfWebRequest $request) {
$blog = $this->getRoute()->getObject();
// retrieve the blogposts via a PEER method (I don't have any clue about Propel ;))
$this->blogposts = however.you.get.the.blogposts();
}
Then create a template bloglistSuccess.php where you show the posts.
Or, you can redirect or forward to the admin module for the blogposts if you have such a module. There you have probably to override the list action to accept the ID parameter of the blog and extend the query to filter posts by this blog id.
There is nothing wrong in doing a redirect or forward, it is not a hack ;)
Edit after comment:
I would also suggest that you forward the request.
No you don't have to change the routing you can just append the parameter like you suggested.
For overriding I reconsidered that it would be better if you override the buildQuery method (again). (I can't remember how this method was called with Propel, I hope you get what I mean).
So it would look like this:
class blogpostAdminActions extends autoBlogpostAdminActions
{
//...
protected function buildQuery()
{
$query = parent::buildQuery();
$request = $this->getRequest(); // <- I am not sure about this method call but there is one that gives you the webRequest.
if ($request->hasParamter('blog_id'))
{
$query->andWhere('blog_id = ?', $request->getParameter('blog_id'));
}
return $query;
}
}
Of course you have to change this to Propel criteria, but I assume you can do that ;)
Hope this helps you.

Resources