Rails associations and create - ruby-on-rails-3

I have a few models set up as Company and Employee. A company has many employees and a company should obviously be able to manage their employees.
What is the best approach to controller routing here? When a company want's to add a new employee should I route to the companies controller or to the employees controller?
For e.g. I could route to companies/:id/edit and then use a form with nested attributes to add employees. I could also just route to employees/new, or I could even use a nested resource and route to companies/:id/employees/new.
What do you think?
By the way I'm using STI, so Company < User and Employee < User

That's a good question. Here is what I think of the three options:
Routing to companies/:id/edit is unacceptable. Although you do edit a company by adding employees it is not meant for this purpose. This route should be used in order to edit company fields like company name, location etc.
Routing to employees/new is a good option, but not the one I would go on.
This is the best option in my opinion. In your case nested resources are created only in the context of their parent resource, so every aspect of you application should follow this. This includes the url for creating these nested resources, and the creation method itself which should be done through #company.employees.create!(params[:employee]) and not by Employee.create...

I think maybe it's not the best, but it's convenient, easy understand, and follow the rails way. You should use nested routes:
resources :companies do
resources :employees
end
Now you will have some routes like this:
company_employees GET /companies/:company_id/employees(.:format) employees#index
POST /companies/:company_id/employees(.:format) employees#create
new_company_employee GET /companies/:company_id/employees/new(.:format) employees#new
So, When you create a new employee, you know which company that employee belongs to thanks to :company_id. All codes for create new employee, update, destroy... of course, will be put in EmployeesController. Then you need to build a nested form for create new employees belong to one company.
If you want create, edit, update... company? Just create new resources for it:
resources :company
So, you can edit company, as in your question writen, through path: companies/:id/edit.

Related

Adding lookups to given view

I'm just getting into Yii. I have a simple relational db. I have a "client" table related to "orders" table (client:id to orders:client_id). If I build my CRUD for orders i naturally see client_id, however I'd rather add a lookup for client name somehow
I have found how to do this on new and update _forms by adding a dropDownList. The list based views seem a little more complex. I can see that actionIndex() in the controller is gathering data and passing it to index.php, finally through to _view, but I can't find any help on where and how I should break into this with my lookup returning the client name
I'd appreciate any help
thanks
Check the Yii documentation about relations. You will need to create a relation in your orders table, lets call it client, Then in your list view where it generates client_id you can put client.name instead. Now you will need to make sure that you have the appropriate label because in the generated model it will only have a label for client_id, and you need a label for client.name. Yii will guess, or you can add it, or you can modify the label for client_id, and instead of using client.name in the view you can use
array(
'name'=>'client_id',
'value'=>$model->client->name,
)
I tend to gravitate towards more explicit definitions rather than shortcuts, but to each his own.

Rails 3 destroy oldest item in database if user owns more than 10

I have an Activity stream I have designed using STI in rails 3.
I want to do a check to see if a user has more than 10 activity items on create. When a user creates his 11th Activity in the database, I want it to destroy the oldest record * essentially the first record the user made and so on.* This way I am keeping my database clean of thousands of old useless records.
I am assuming I would start at the model level, but since I dont want to define the "current_user" in the model, it should be in the controller.
Any help would be appreciated to accomplish this task, I am fairly new at these type of more advanced tasks in rails.
You can hook this logic up in an AR callback. Assuming you kept rails conventions when modeling you classes, and each activity belongs to a user, you can then easily do the following in your Activity model:
after_save do |record|
if Activity.where(:user => record.user).count >= 11
Activity.where(:user => record.user).order('created_at asc').first.destroy
end
end
I guess this will create three transactions to the db (one for count, another to find the first record, and one to delete it). I wonder if there's a more efficient way to do this, as it will be invoked on every Activity#save...

Rails ActiveRecord: How to select all users with a given permission?

I've got a model called Users, some of whom are considered Authors. This is accomplished through a table called Roles, which lists a number of different roles: "Author" is one. A many-to-many association in a table called Permissions links Roles and Users.
To check whether a User has the Author permission, I have a method that runs through the Permissions linked to that particular User and returns whether any of them also links to the Author permission.
This system has served me well. However, it makes it clunky to search and order the Authors on the site. What I'd like to do is something simple and graceful, ideally like a named scope that will allow me to say things like Users.authors.order("date_joined") or something like that.
As it is right now, I don't have any way to get the group of "Author" users other than pulling all Users out of the database, running through them one at a time, searching for their Author permission, and then adding them to an array of Users if it is found.
This seems rather ungraceful, especially as I have to do it every time I want to present the list of Authors in a view.
Is there a better way?
EDIT -- Solution:
Following the helpful advice below and the tips from http://railscasts.com/episodes/215-advanced-queries-in-rails-3?view=asciicast I was able to put together the following.
In User.rb:
class User < ActiveRecord::Base
scope :authors, joins(:permissions) & Permission.author_permissions
scope :admins, joins(:permissions) & Permission.admin_permissions
In Permission.rb:
class Permission < ActiveRecord::Base
scope :author_permissions, where("role_id = ?", Role.find_by_rolename("author"))
scope :admin_permissions, where("role_id = ?", Role.find_by_rolename("administrator"))
And voila! Now I can call Users.authors and it works like a charm.
Keep the schema structure that you have but make sure to add the proper table indexes.
Then to query for users in specific roles you can do
User.all(:joins => :roles,
:conditions => {:roles => {:id => pick_a_role_id}})
have you looked at CanCan? It will probably require a little refactoring, mostly to create a current_user method. A guide to roles can be found here

Nested resource check

I have a Rails form, where is reported the user and the skills of the user (the association is many to many) so I use accepted_nested resource in the form
Everything works okkey, the user have the chance to create a new skill and associate themself to it.
The problem is that if a skill with the same name already exists, I don't want that one more skill with the same name is created, I just want an association with the user and the already existing skill.
Do I have to leave the nested resource approach and performing some controls in the controller in order to choose if create or just associate the skill ?
Tnx
You could use Rails' find_or_create_by method to find or create the skill by whatever criteria you choose. Then add that to the user's skill collection. I don't know what your code looks like, but something like this:
#skill = Skill.find_or_create_by_name(params[:skill][:name])
#user.skills << #skill

Organising resource (URI) in REST API

Scenario 1
In my web application say for there is a screen for adding an employee to system. As soon as user tabs after entering name of the employee, it generates the employee code automatically (which is the next field) based on some logic and already present records in the database.
Now I want to expose rest API for this application so that third party devs can build on top of it. So, I will have a resource called as /Employee which will respond for GET, PUT and DELETE verbs. But when a client needs to autofill the code, which is a GET operation, it will be on what resource? Should I make a new resource /EmployeeCodeFor/{Name} or I should get it on /Employee/{Name}/GenerateCode? If I go with /Employee/{Name}/GenerateCode then what about my resource to GET, PUT and DELETE for Employee i.e. actually /Employee/{Id}?
Scenario 2
Here lets take the case of a stackoverflow post. So lets say the resource would be /Post/{Id}. In the same way as in the previous example it lists me possible duplicate question as soon as I tab out of the Title field.
Again on what URL I should get those possible duplicates?
I can't think of more scenarios just now. But many such kind of scenarios may come up in real life application development. How to implement them in RESTful way?
Update on scenario 1
Code and Id are two different fields. Id is primary key, code can be duplicate across departments just to illustrate. Also to generate a code, name should be provided first. So, if user types a name "FirstName LastName" then server might generate FL003 as code assuming that there are already two more employees with firstname starting from F and lastname starting from L in the said department. Department can be identified based on the logged in user.
One way to allow the server an opportunity to pre-fill a bunch of elements in a new resource is to do
POST /Employees
{with empty body}
=>
201 Created
Location: http://example.org/employee/3443
<Employee Id="3443">
<Code>E1001</Code>
<FirstName></FirstName>
<LastName></LastName>
</Employee>
This gives the server one chance to provide default values. If you are looking for a more interactive way for the server to provide feedback during the input, I have another approach but it will take quite a bit more explaining.
Scenario 1
Let say your employee code is a unique identifier. In this case, to get it, you would allow the user to complete any field for the new employee and then make a POST. The server would generate the code and respond to the POST with a link to /Employee/{generated_code} which is the record for your newly created employee.
A GET on /Employee would return a list of all employees. A GET on /Employee/{a_code} will give you the employee detail.
Scenario 2
You could have some kind of query on the /Post collection like /Post?title_like={question_title}. A GET /Post?title_like=REST How to would return you a list of all questions containing "REST How to".