Nested resource check - ruby-on-rails-3

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

Related

Rails associations and create

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.

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

Rails: cannot change email after signed up?

i have a User model and some common columns, such as name, email, password, etc.
and here is the thing:
i donot want a user changing his email address after signed up, what should i do?
just don't include the email field in the update form?
and i think the attr_accessible is not for this use either.
what do you suggest? thanks a lot.
What you need is
attr_readonly
The documentation says the following
Attributes listed as readonly will be used to create a new record but update operations will ignore these fields.
So, a new record can be created with an email but you can never change it (without a hack) after the record has been created.

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".

Getting user profile data in Silverlight 4

I am fairly new to Silverlight and RIA services, and I am trying to build a small project to understand it. So basically I created a Business Application, and I have the normal Login screen where I can add a user. That is fine and I can add a user and get him into the aspnet_Users table. Now I have created some extra fields, like Mob No, Tel No, DOB, Locality etc, which I have put in a table I have created called the UserProfile, and my idea is to get the username that was registered, and insert it into my UserProfile table with the other relevant data.
So I created a page called Profile.xaml, I created a UserProfileDomainService.cs where I have just one query, to get the user profile data from the table, and then created a Details DataGrid on my page, and the QueryName in my case is GetUserProfilesQuery(). Now what i wish to do is, get the user logged in, get his username, and check in my table to see if there is already data in the table. If there is populate the fields on the DataGrid with data, so that the user can modify this data, and if not, allow the user to insert data into the table.
So I have created a UserProfileViewModel class, and I want to create the query to get the data relevant to this user. However I got stuck on how to do all this, and how to get the user logged in.
Can anybody give me some advice or point me to some tutorials on how I can achieve this?
Thanks a lot and your help is very much appreciated.
In your domain service query you can use ServiceContext.User.Identity.Name to get the information specific to that user to include in your db query. I do something similar in our project.
We use entity framework so the LINQ to Entities query looks like:
return this.ObjectContext.UserSnapins
.Include("Snapin.EvolutionModule")
.Where(si => si.User.UserName == ServiceContext.User.Identity.Name)
.OrderBy(si => si.PageOrder);