I'm very new to rails and am having some trouble. I have a model called BusinessDates that consists of two tables, calendar_date and seasonality (you can ignore seasonality). What I'm trying to achieve is to be able to move through them easily like folders.
It took me a few solid days of google-foo, but I was able to have the index display a list of each unique year in order as links with friendly_ids. From here I want to click on it and have it link to a new view that displays a list of each unique month in that particular year in order as links with friendly_ids. Then (as you could guess) have it display on another new view a list of all the days in the selected month in the selected year. I want the url to be business_dates/2016/5/21 or in other words business_dates/(year)/(month)/(day).
My issue: I don't know where to go from here. I can't even seem to find any info on making a second level deep non-static url without either making each year month and day separate models (want to avoid that), or what looks like a rube goldberg machine to kinda get there but without views for each page (You'd have to just type the full date into the url).
Please help a beginner who feels very lost!
Controller:
def index
#years = BusinessDate.pluck(:calendar_date).map{|x| x.year}.uniq
end
index.erb.html
<table>
<tr>
<th>Year</th>
</tr>
<% #years.sort.each do |year| %>
<tr>
<td><%= link_to year, business_date_path(year) %></td>
</tr>
<% end %>
</table>
You can create a custom route. Since I don't know the exact controller actions etc that you are using, I will give you a general answer. You can route like (will hit BusinessDatesController's :show_full_date action):
get 'business_dates/:year/:month/:day', to: 'business_dates#show_full_date'
You can link to it like (run rake routes to check correct path):
<%= link_to your_date, full_date_business_dates_path('1985','5','21') %>
The important thing to understand here is that the path helper is in the end just a method that can take arguments. What it can accept is defined in the routes.rb. So, in our case, it will :year, :month and :day parameters.
Once you click this link and hit the :show_full_date action, you can extract the year, month, date using params[:year], params[:month], params[:day] and do with them whatever you need to do. You can similarly define routes for just the year or the month. Hope this helps.
EDIT: You can also give the as: option in the route definition to give a specific name to the path, like as: 'my_funky_name'.
Also, I should add that you should keep such custom routes to a minimum. When it is necessary, then do it. Otherwise stick to the defaults.
I finally figured it out and got it working, so I'll share my answer. big props to arunt for the help! It's a bit messy and probably not the right way I should be doing this, but my first goal was to get it to work and learn how it works along the way. Now I'm looking to tidy up and learn best practices.
Routes
Rails.application.routes.draw do
resources :business_dates, except: :show
get '/business_dates/:year/:month/:day', to: 'business_dates#edit_date', as: 'edit_date'
get '/business_dates/:year/:month', to: 'business_dates#by_days', as: 'by_days'
get '/business_dates/:year', to: 'business_dates#by_months', as: 'by_months'
delete '/business_dates/:year/:month/:day', to: 'business_dates#delete_date', as: 'delete_date'
Controller
class BusinessDatesController < ApplicationController
def index
#business_dates = BusinessDate.all
#years = BusinessDate.pluck(:calendar_date).map{|x| x.year}.uniq
end
def new
#date = BusinessDate.new
end
def by_months
#months = BusinessDate.where("strftime('%Y', calendar_date) = ?", params[:year])
#months = #months.pluck(:calendar_date).map{|x| x.strftime('%m')}.uniq
end
def by_days
#days = BusinessDate.where("cast(strftime('%Y', calendar_date) as int) = ? AND cast(strftime('%m', calendar_date) as int) = ?", params[:year], params[:month])
end
def edit_date
set_business_date
end
def create
#date = BusinessDate.new(date_params)
if #date.valid?
#date.save
redirect_to by_days_path(#date.calendar_date.year, "%02d" % #date.calendar_date.month)
else
flash.now[:alert] = "New business date could not be saved"
render action: "new"
end
end
def update
#set_business_date
#date = BusinessDate.find(params[:id])
#date.update(date_params)
redirect_to by_days_path(#date.calendar_date.year, "%02d" % #date.calendar_date.month)
end
def delete_date
set_business_date
#date.destroy
redirect_to by_days_path(params[:year], params[:month])
end
private
def set_business_date
#date = BusinessDate.where("cast(strftime('%Y', calendar_date) as int) = ? AND cast(strftime('%m', calendar_date) as int) = ? AND cast(strftime('%d', calendar_date) as int) = ?", params[:year], params[:month], params[:day]).first
end
def date_params
params.require(:business_date).permit(:calendar_date, :seasonality)
end
end
index.html.erb
<h1>Business Dates by Year</h1>
<table>
<tr>
<th>Calendar Date</th>
</tr>
<% #years.sort.each do |year| %>
<tr>
<td><%= link_to year, business_date_path(year) %></td>
</tr>
<% end %>
</table>
<br>
<%= link_to 'Create New Business Date', new_business_date_path %>
by_months.html.erb
<h1><%= params[:year] %></h1>
<table>
<tr>
<th>Months</th>
</tr>
<% #months.sort.each do |month| %>
<tr>
<td><%= link_to Date::MONTHNAMES[month.to_i], by_days_path(params[:year], month) %></td>
</tr>
<% end %>
</table>
<br>
<%= link_to 'Create New Business Date', new_business_date_path %>
<br>
<%= link_to 'Back to Years', business_dates_path %>
by_days.html.erb
<h1><%= Date::MONTHNAMES[params[:month].to_i] %>, <%= params[:year] %> <%= params[:id] %></h1>
<table>
<tr>
<th>Date</th>
<th>Seasonality</th>
<th>ID</th>
</tr>
<% #days.sort.each do |day| %>
<tr>
<td><%= day.calendar_date.day %></td>
<td><%= day.seasonality %></td>
<% %>
<td><%= day.id %></td>
<td><%= link_to 'Edit', edit_date_path(day.calendar_date.year, "%02d" % day.calendar_date.month, day.calendar_date.day) %></td>
<td><%= link_to 'Delete', delete_date_path(day.calendar_date.year, "%02d" % day.calendar_date.month, day.calendar_date.day), method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
<br>
<%= link_to 'Create New Business Date', new_business_date_path %>
<br>
<%= link_to 'Back to Months', by_months_path %>
<br>
<%= link_to 'Back to Years', business_dates_path %>
It's all working fine, but I wish I could figure out my :id issue. Not sure how to find a record by :id while using the :year/:month/:day url convention. It's not an issue for this app, considering there should never be more than one of the same date, but it'd be helpful and I'm sure it would cut down on having to search for the record by params[:year],[:month], and [:day]. This thing was a holy terror, but I certainly learned a lot about the differences between arrays, hashes, symbols, attributes, models, methods, and instance variables along the way!
Related
I am new to Rails and I am struggling on something which sounds easy but can not get it to work. I have two models Students and Attendances.
Student model:
name lastname classroom_id
Attendance model:
present:boolean absent:boolean halfday:boolean attnd_date:date student_id
Students has_many :attendances and attendance belongs_to :student.
I can make an entry for individual student and take their attendance however I want to generate a view where I show all the students (or show all students for a given classroom) and next to each student name I would like to show the three checkboxes so that I can mark who is present and absent in one go rather than one by one and submit the form.
Any help here is much appreciated. Using Rails 4 and ruby 2.2.0
Thanks
You can make an edit action, where you will find the classroom for which you want to mark attendances.
class AttendancesController < ApplicationController
def edit
#classroom = Classroom.find(<classroom-id>)
end
def update
end
end
In your view edit.html.erb
<%= form_for(#classroom, url: '/attendances/:id', method: :put) do |f| %>
<table>
<%- #classroom.students.each do |student| %>
<tr>
<td><%= student.name %></td>
<td><%= checkbox_tag "attendances[#{student.id}][present]" %></td>
<td><%= checkbox_tag "attendances[#{student.id}][absent]" %></td>
<td><%= checkbox_tag "attendances[#{student.id}][halfday]" %></td>
</tr>
<% end %>
</table>
<%= f.submit %>
<% end %>
This way, when you submit the form, you will receive these params in your update action:
`{ attendances: { '1' => { present: false, absent: true, halfday: false }, '2' => { present: true, absent: false, halfday: false }, ... } }`.
Then you can write logic in your action to save these details to database.
Note: This is kind of pseudo code. Please check the syntax and options for different html tags.
Thanks to #Jagdeep Singh for getting me up and running. I have now made the process more simple so I can get my head around. I just want to get the list of all students and create their attendances.
My view:
<% #students = Student.all %>
<%= form_for(:attendances, url: '/admin/attendances/') do |f| %>
<table>
<%= #today %>
<th>Name</th><th>Present</th><th>Absent</th><th>halfday</th>
<%- #students.each do |student| %>
<tr>
<td><%= student.first_name %></td>
<td><%= check_box_tag "attendances[#{student.id}][present]" %></td>
<td><%= check_box_tag "attendances[#{student.id}][absent]" %></td>
<td><%= check_box_tag "attendances[#{student.id}][halfday]" %></td>
</tr>
<% end %>
</table>
<%= f.submit %>
<% end %>
when I click on create attendance button it just creates just one with record with all default params and.
I am sorry I am still learning but once I get my head around on how I can create attendances for all 10 students i have in one go.
For a current project, I have duplicate code between views, and I'm not sure of the best route to refactor it.
I appear to be in a position where I can have duplicate code across various .html.erb files, or I could put identical code into a partial and use conditionals. I've always heard logic should stay out of views. Neither option seems ideal, and I don't currently know of alternatives.
To illustrate my question, I created a simple rails app called animals. I scaffolded for two models: one for cat and one for dog. Images display their corresponding attributes:
Displaying #cats and #dogs is pretty much the same. Cats just have a column for meows while Dogs have a column for barks, and a dog has the additional attribute column of plays_catch.
Lets say we choose to reduce the duplicate code for displaying cats and dogs by making a shared view partial:
#views/shared/_animal.html.erb
<tr>
<td><%= animal.name %></td>
<td><%= animal.age %> </td>
<% if animal.class == Cat %>
<td><%= animal.meows %> </td>
<% end %>
<% if animal.class == Dog %>
<td><%= animal.barks %> </td>
<td><%= animal.plays_catch %> </td>
<% end %>
</tr>
Then to render #cats = Cat.all:
<%= render partial: "shared/animal", collection: #cats %>
Then to render #dogs = Dog.all:
<%= render partial: "shared/animal", collection: #dogs %>
Obviously it would be overkill to do something like this for this specific example, but the real world project I'm applying it to would not be overkill.
The overall question is: how do you remove nearly identical code that iterates over collections, where the only difference is adding/removing a column of information? It just doesn't feel right to put that logic in the view itself, and leaving the duplication feels wrong.
You could use decorators and add methods that return the extra column(s):
class DogDecorator < Draper::Decorator
def extra_columns
[:barks, plays_catch]
end
end
class CatDecorator < Draper::Decorator
def extra_columns
[:meows]
end
end
...
<% animal.extra_columns.each do |column| %>
<td><%= animal.attributes[column.to_s] %>
<% end %>
...
<% #cats = CatDecorator.decorate_collection(Cat.all)
<%= render partial: "shared/animal", collection: #cats %>
You can use respond_to? to solve the problem more generically. The view logic doesn't feel so wrong when it's more generic.
<% [:meows, :barks, :plays_catch].each do |method| %>
<% if animal.respond_to?(method) %>
<td><%= animal.send(method) %> </td>
<% end %>
<% end %>
You can add a method of the same name to both Cat and Dog classes which would return the specific instance attributes names and values. I'd recommend returning two arrays (one with the names of the fields, other with the fields' values, or vice-versa) since hashes are not exactly ordered. This way you can control the order in which they'll appear in the view.
For example:
#models/cat.rb
def fields_and_attributes
fields = ["Name","Age","Meows"]
attributes = [self.name, self.age]
if self.meows
attributes.push("Yes")
else
attributes.push("No")
end
[fields,attributes] # make sure each attribute is positioned in the same index of its corresponding field
end
#models/dog.rb
def fields_and_attributes
fields = ["Name","Age","Plays catch"]
attributes = [self.name, self.age]
if self.plays_catch
attributes.push("Yes")
else
attributes.push("No")
end
[fields,attributes] # make sure each attribute is positioned in the same index of its corresponding field
end
#controllers/animals_controller.rb
def display_animals
#animals = Cat.all + Dog.all # an array containing the different animals
end
#views/display_animals.html.erb
for i in (0...#animals.size)
fields_and_attributes = #animals[i].fields_and_attributes
for f in (0...fields_and_attributes[0].size)
<p><%= fields_and_attributes[0][f] %> : <%= fields_and_attributes[1][f] %></p>
end
end
Here, we first iterate over all of the animals and call the .fields_and_attributes method of that specific record; we then iterate over the results of calling that method, displaying fields and attributes in the same order as the one defined within the method and also guaranteeing that the code will display every field and every attribute regardless of the difference in the total number of fields for each different animal.
I don't know of any canonical way to accomplish this, but I would use one partial for this in the following way:
<tr>
<% animal.attributes.each do |_, value| %>
<td><%= value %></td>
<% end %>
</tr>
You can get rid of repeated attributes calls by providing in the partial a local variable with pre-obtained model attributes.
EDIT: if you only want to display some attributes.
# Declare whitelist of attributes
# (you can also declare a blacklist and just calculate the difference between two array: all_attributes - blacklist_attributes):
<% whitelist = [:name, :age, :barks] %>
<%= render partial: 'shared/animal',
collection: #dogs,
locals: {attrs: (#dogs.first.attributes.keys.map(&:to_sym) & whitelist)} %>
views/shared/_animal.html.erb:
<tr>
<% attrs.each do |attr| %>
<td><%= animal[attr] %></td>
<% end %>
</tr>
Below is my answer after reviewing posted answers. Basically:
I left the differences within each scaffold model's index page
I made shared partials for common table headers and table data
code below:
#app/views/cats/index.html.erb
<h1>Listing Cats</h1>
<table>
<thead>
<tr>
<%= render partial: "shared/cat_dog_table_headers" %>
<th>Meows</th>
</tr>
</thead>
<tbody>
<% #cats.each do |cat| %>
<tr>
<%= render partial: "shared/cat_dog_table_data", locals: {animal: cat} %>
<td><%= cat.meows %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Cat', new_cat_path %>
And for the dogs:
#app/views/dogs/index.html.erb
<h1>Listing Dogs</h1>
<table>
<thead>
<tr>
<%= render partial: "shared/cat_dog_table_headers" %>
<th>Barks</th>
<th>Plays catch</th>
</tr>
</thead>
<tbody>
<% #dogs.each do |dog| %>
<tr>
<%= render partial: "shared/cat_dog_table_data", locals: {animal: dog} %>
<td><%= dog.barks %></td>
<td><%= dog.plays_catch %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Dog', new_dog_path %>
The shared table headers for cats and dogs:
#app/views/shared/_cat_dog_table_headers
<td><%= Name %></td>
<td><%= Age %></td>
The shared table data for cats and dogs:
#app/views/shared/_cat_dog_table_data_headers
<td><%= animal.name %></td>
<td><%= animal.age %></td>
I am making a resume application to list my employment history, education history and other responsibilities. This is my first rails application on my own without a tutorial, but much of what I do is just following the same actions. All the code is here: https://github.com/victorman/portfolio
Quick summary. I ajaxed my app a bit, and got it to work. But I had a template with the exact same html as part of a view, so I replaced that portion with a render :partial.... The result was twice the html as before. Below is a more detailed description of what I did to the app.
I made two scaffolds, one for Jobs and one for Categories. Jobs has a foreign key to categories.
I made the Jobs view list a link for each category. The jobs#index controller then only finds the rows in the jobs table for that category.
Then I decided to throw some ajax in there so that clicking a link would only reload the relevant data. I added a respond_to at the end of the jobs#index method.
def index
#find which jobs to display based on category_id in the url params
#if no category_id param is given default to 1
unless params.has_key? :category_id
#jobs = Job.find(:all, :conditions => {:category_id => 1})
else
#jobs = Job.find(:all, :conditions => {:category_id => params[:category_id]})
end
respond_to do |format|
format.html
format.js #index.js.erb
end
end
I made a index.js.erb file that retrieves the new data and replaces the old.
var jobs = $("<%= escape_javascript(render(:partial => #jobs))%>").hide();
$("#jobs_table").replaceWith(jobs);
$("#jobs_table").fadeIn();
I added remote: true to the links in the jobs index.html.erb file.
<ul>
<% Category.all.each do |category| %>
<li><%= link_to category.name, { :controller => "jobs", :category_id => "#{category.id}" }, :class => "category_link", remote: true %></li>
<% end %>
</ul>
And I made the template partial where the jobs were displayed. it would never find _jobs.html.erb so i had to name it _job.html.erb
<tbody id="jobs_table">
<% #jobs.each do |job| %>
<tr>
<td><%= job.organization %></td>
<td><%= job.location %></td>
<td><%= job.details %></td>
<td><%= job.start_date %></td>
<td><%= job.end_date %></td>
<td><%= link_to 'Show', job %></td>
<td><%= link_to 'Edit', edit_job_path(job) %></td>
<td><%= link_to 'Destroy', job, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
after all that it worked but I still hadn't DRY'd up the code so I removed the repeated section from index.html.erb which is in _job.html.erb (as shown above) and replaced it with this.
<%= render :partial => #jobs %>
and now it gives me two identical <tbody> tags with id="jobs_table". Why is this giving duplicate data?
You've got a lot to fix...
Create a nested route in your routes.rb:
resources :jobs
resources :categories do
resources :jobs
end
index.html.erb:
<h1>Listing jobs</h1>
<div>
<ul>
<% Category.all.each do |category| %>
<li><%= link_to category.name, category_jobs_path(category),
class: "category_link", remote: true %></li>
<% end %>
</ul>
</div>
<table>
<thead>
<tr>
<th>Organization</th>
<th>Location</th>
<th>Details</th>
<th>Start date</th>
<th>End date</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody id="jobs_table"><%= render partial: #jobs %></tbody>
</table>
<br/>
<%= link_to 'New Job', new_job_path %>
the index of jobs_controller.rb can (should) be refactored to:
class JobsController < ApplicationController
def index
#jobs = Job.where(category_id: params[:category_id] || 1)
respond_to do |format|
format.html
format.js
end
end
end
and the index.js.erb response also should be refactored to:
$("#jobs_table").html("<%= escape_javascript(render partial: #jobs) %>")
$("#jobs_table").fadeIn()
there are some naming issues which should be more pregnant like:
jobs instead of jobs_table
and
category instead of category_link
Also trying to find a Job belonging to Category with 1 is odd. Deal with a different response than a default Category with id 1 (hard coded ids are one of the worst things you can do).
The div around the Categories list is useless (keep your rendered HTML slim and readable).
The problem is due to not understanding when rails manipulates singular vs plural.
Calling render partial: #jobs automagically goes out to the partial _job.html.erb for each element in #jobs. But then the partial goes through each element again because of #jobs.each do |job|.
To fix it, in the render line, replace #jobs with "jobs" and rename _job.html.erb to _jobs.html.erb.
Alternatively, save a step by just replacing #jobs with "job" and keep the template name _job, but this reinforces an incorrect naming scheme.
index.html.erb:
<tbody id="jobs"><%= render partial: "jobs" %></tbody>
index.js.erb:
$("#jobs").html("<%= escape_javascript(render(partial: 'jobs'))%>")
Now it will just search literally for the _jobs template (_jobs.html.erb) and render it once as opposed to going to the singular version of the name and rendering that many times.
The user of my application submits a request via a form and receives a set of numbers. The numbers constantly update throughout the day and I need a way to track the average of the last two numbers.
It'll work something like this:
How much experience do you have now?: 13000000
How much experience do you have now?: 13200000 (one hour later)
Then the user should be redirected to a page where the "experience per hour" is displayed: 200000
My application can currently only make the request for the number. Now I need a way to save that number and the time it was created, allow for a second number to be searched, and then perform a computation on them.
Here are the contents of my files.
home.html.erb with the form:
<h1>Welcome to xpTrack</h1>
<%= form_tag("/search", method: "get") do %>
<%= label_tag(:username, "Search for:") %>
<%= text_field_tag(:username) %>
<%= submit_tag("Search") %>
<% end %>
This form passes the username the user enters into params[:username] in the controller:
SearchController
class SearchController < ApplicationController
def home
require 'open-uri'
#username = params[:username]
#url = "http://hiscore.runescape.com/index_lite.ws?player=#{#username}"
#doc = Nokogiri::HTML(open(#url))
#stats = #doc.text.split(' ').map{|a| a.split(",") }
#skills = %w(overall, attack, defence, strength, constitution, ranged, prayer, magic, cooking, woodcutting, fletching, fishing, firemaking, crafting, smithing, mining, herblore, agility, thieving, slayer, farming, runecrafting, hunter, construction, summoning, dungeoneering, divination)
#max = 13034431
end
end
This view is rendered after searching:
<h1>
<%= #username.capitalize %>
</h1>
<table>
<tr>
<th>Skill</th>
<th>Rank</th>
<th>Level</th>
<th>Experience</th>
<th>Experience to 99</th>
</tr>
<% #skills.each_with_index do |skill, i| %>
<tr>
<td><%= skill.chomp(',').capitalize %></td>
<td><%= #stats[i][0] %></td>
<td><%= #stats[i][1] %></td>
<td><%= #stats[i][2] %></td>
<% if #stats[i][2].to_i < #max %>
<td><%= #max - (#stats[i][2]).to_i %></td>
<% end %>
</tr>
<% end %>
</table>
Link to the application at Heroku: http://runescapecalc.herokuapp.com/
When searching, use the username 'Brink'.
I'm new to Ruby on Rails & to web programming.
In my application I have two models; Directorate which has_many :users, and User which belongs_to :directorate.
When creating a new user, I use <%= f.collection_select(:directorate_id,Directorate.all, :id, :name) %> in the new.html.erb form to assign the new user to specific directorate. However, I want to build a user-friendly interface for the dba that lists all directorates; and listing all users beside each directorate, with a link to assign any user to a specific directorate.
What I did is the following:
In Directorate model, I defined the following function:
def assign_user!(user)
user.update_attributes(directorate_id: #directorate)
end
and in the directorates controller, I defined the following action:
def assign_user
#directorate = params[:directorate]
assign_user! params[:user]
redirect_to directorates_url
end
Now, directorates/index.html.erb contains the following:
<h1>Listing directorates</h1>
<table>
<tr>
<th>Name</th>
<th>Info</th>
</tr>
<% #directorates.each do |directorate| %>
<tr>
<td><%= directorate.name %></td>
<td><%= directorate.info %></td>
<td><%= link_to 'Show', directorate %></td>
<td><%= link_to 'Edit', edit_directorate_path(directorate) %></td>
<td><%= link_to 'Destroy', directorate, confirm: 'Are you sure?', method: :delete %></td>
<%= #directorate = directorate%>
<%= render 'users_form' %>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Directorate', new_directorate_path %>
and, -users_form.html.erb contains the following form (which is supposed to list all users beside each directorate, with a link to assign any user to a certain directorate):
<h1>Listing Users</h1>
<table>
<tr>
<th>User Name</th>
</tr>
<% #users.each do |user| %>
<tr>
<td><%= user.username %></td>
<td><%= link_to 'Assign to Current Directorate', {controller: 'directorates', action: 'assign_user', directorate: #directorate, user: user}, :method => :put %></td>
</tr>
<% end %>
</table>
<br />
Here is the problem, when listing directorates & click on the 'Assign to Current Directorate' I receive the following error:
http://127.0.0.1:3000/directorates/assign_user?directorate=4&user=5
ActiveRecord::RecordNotFound in DirectoratesController#update
Couldn't find Directorate with id=assign_user
Rails.root: /home/ehab/sites/IAMS
Application Trace | Framework Trace | Full Trace
app/controllers/directorates_controller.rb:61:in `update'
Request
Parameters:
{"_method"=>"put",
"authenticity_token"=>"L5tz3hv2IW0meE79qUq0/tjfGKwDlpC23hOeAWtmTvk=",
"directorate"=>"4",
"user"=>"5",
"id"=>"assign_user"}
It's clear that the params is submitting "id"=>"assign_user" which I don't want, what i want is "id"=>"directorate.id" (4 in the above example). What shall I do to fix this issue?!
first of all your routes should say that assign_user is a member method on a certain directorate object:
resources :directorates do
member do
put :assign_user
end
end
second you say you define assign_user! in Directorate model and assign_user in DirectoratesController but both methods imply that they share same object state like instance variable #directorate which is not true
your controller method assign_user should look vaguely like
def assign_user
#directorate = Directorate.find params[:id]
#user = User.find params[:user_id]
#directorate.assign_user! #user
end
and model method should look like
def assign_user!(user)
user.update_attributes(directorate_id: self.id)
end
and even that i would switch around to instead of telling Directorate to change user's attributes you would tell User to assign itself to whatever controller wants.
and the final bit is your link that assigns user to directorate:
link_to 'Assign to Current Directorate',
assign_user_directorates_path(#directorate, :user_id => user)
0 lines of code above were tested for even syntactical correctness, DO NOT copy-paste, read and understand