Using a 'new' form to make database changes - ruby-on-rails-3

I have a user, who wants to be able to take vacation days off from work. My view looks like this:
<h2>Request Days Off</h2>
<%= form_for(#user, :as => :user, :url => vacation_days_path) do |f| %>
<div><%= f.label "How many vacation days would you like to take?" %>
<%= f.number_field :vacation_days %></div>
<div><%= f.submit "Submit" %></div>
<% end %>
In my controller, I have new and create methods. In all examples of the 'create' method I see on the internet, there is a line of code similar to
#person = User.new(user_params) or whatever
My issue is that I don't have a vacation_days model. Only a controller. I want to edit the User database, but creating a new user cannot be the answer (right?).
How do I create a working create method?

This is not really RESTful... However, if you want to update an existing user, you can do so like this
#user = User.find(params[:id])
#user.update_attributes(params[:user])
where params[:id] would hold the id of the user you want to update and params[:user] would hold the attributes you want to update.
Since you are using form_for(#user) with its form builder, it should be fine.

It doesn't seem to me that you need your separate controller for vacation days. Simply have a vacation_days/edit view, which contains your form, and have it submit to users/update.
For clarity, your action should be editing and updating your user, rather than 'creating' one. So, your controller action to update your user should have the line:
#user.update_attributes(params[:user])

Related

How to create a newsletter partial

I'm trying to create a very simple email signup form, where the user can just enter their email and press submit.
I'd like the signup form to be a partial, so I can use it anywhere on the site.
Forms are coded like this:
<%= form_for #subscription do |f| %>
How to do tell the form that #subscription is a Subscription.new if, say, the current view, controller, and action is the home page?
Thanks!
As an option you can do:
<%= form_for Subscription.new do |f| %>
One thing though, I haven't tried this myself. Try it and see if it works.
Edit:
Sorry, I didn't get the question in the first read.
You can set the #subscription instance variable to Subscription.new in the home controller, and then, pass it to the partial (inside the main view) like this:
<%= render partial, :subscription => #subscription %>
Hope this helps.
You'll have to make sure that #subscription is instantiated before calling the partial ... or do :
<%= form_for #subscription || Subscription.new do |f| %>
So if #subscription exists, it uses it. If not, it'll fall back to Subscription.new
You can declare #subscription as Subscription.new right in the home action

Rails syntax Passing POST parameters from a form to a controller

I'm new to Rails (and fairly new to programming in general) and I am building a web app for myself as a way to learn. Right now I am modifying scaffolded forms and such.
My question is with the "create" method in one of my controllers. There are two entities I am concerned with: the User table and the Habit table. I created a dropdown box in the _form partial for the Habit views to allow a person to select a user from a list of all available when creating a habit as below
<%= collection_select :user, :id, #users, :id, :first_name %>
The habit controller, of course, has
def new
#users = User.all
...
end
This works fine, and when the form submits it posts two hashes of parameters :habit and :user. Now, when I want to process the form input in the create method, I'm not sure how to use the syntax correctly and assign the user_id to the newly create habit. What I WANT to do is something like this
def create
#habit = Habit.new(params[:habit], params[:user])
end
This, of course, is improper syntax.
def create
#habit = Habit.new(params[:habit])
end
assigns the params from the :habit hash correctly, but then the user_id is left unset.
What works is the following, but the code is very lengthy, assigning each value manually.
def create
#habit = Habit.new(:user_id => params[:user][:id],
:description => params[:habit][:description],
:habit_method => params[:habit][:habit_method],
:time_reqd => params[:habit][:time_reqd],
:will_reqd => params[:habit][:will_reqd],
:active => params[:habit][:active])
end
So my question is, when dealing with a form that posts data in multiple hashes, what is the proper way to pass those parameters into some method in a controller?
So my question is, when dealing with a form that posts data in multiple hashes, what is the proper way to pass those parameters into some method in a controller?
Instead of saying Habit.new( <lots of stuff> ), just use Habit.new(params[:habit]). Rails will try to assign each key in the hash (in this case, the params[:habit] hash's keys) to a matching value on the object.
Thus, if params[:habit] has a :description key, it will be assigned to a field called description on your model. This is called mass assignment and is quite handy.
Now you can just do:
#habit = Habit.new(params[:habit])
#habit.user_id = params[:user][:id]
You may want to read the RoR Getting Started Guide, like this section, for more similarly handy features of Rails.
Change
<%= collection_select  :user, :id, #users, :id, :first_name %>
To
<%= collection_select  :habit, :user_id, #users, :id, :first_name %>
The existing scaffold code should just work after that
Alternate
<%= f.select :user_id, #users, :id, :first_name %>

Using scopes and checkboxes to filter index

Like many questions here on SO, I'm attempting to build a form where checkboxes filter my index view. This would ideally occur with AJAX so I don't reload anything. The problem is that I'm as much of a beginner to Rails and programming as can be so I need help on how to set this up.
The index I want to filter is /users, where the values of the checkboxes are attached to the current_user's profile. For example, consider the following:
<% form_for(current_user.profile) do |f| %>
<tr>
<td class="normal"><%= current_user.profile.current_city %></td>
<td><%= check_box_tag :current_city %></td>
</tr>
<tr>
<td class="normal"><%= current_user.profile.hometown %></td>
<td><%= check_box_tag :hometown %></td>
</tr>
<% end %>
If this worked properly with my model and database, clicking either or both of the checkboxes would render the appropriate profiles in my index partial.
I believe I need to use scopes but don't know to do that with so many profile attributes.
UsersController:
class UsersController < ApplicationController
before_filter :authenticate, :only => [:edit, :update]
def index
#user = User.all
#profile = Profile.all
end
end
User model:
class User < ActiveRecord::Base
attr_accessor :password
has_one :profile, :dependent => :destroy
end
Profile model:
class Profile < ActiveRecord::Base
belongs_to :user
accepts_nested_attributes_for :user
end
Can anyone point me in the right direction here? I've looked at MetaSearch but I want to learn how to do it without a gem for the moment.
So, I think the answer to this question is going to be very similar to the answer on your related question, How to make parts of Profile searchable or not
Basically, you need to tie the check boxes to the setting of either per-column visibility flags, or the creation/destruction of visibility records, depending on how fine-grained your access rights need to be.
That is, checking a check box should set the appropriate visibility flag/record for that user (you can do that via AJAX), and un-checking it will clear/destroy the appropriate visibility flag/record.
IF, on the other hand, the form you're talking is a global, "What partials do I render for my user index page?" kind of form that an admin is editing, then setup a table called whatever you want (partial_renderings?) that contains boolean columns, one for each partial, that get set/cleared when check boxes are checked/un-checked.
Then, the if statement around a partial rendering is something like:
...
<% if PartalRenderings.show_hometown %>
<%= render :partial => "user_hometown", :locals => {:user => #user}
<% end %>
...
The partial_renderings table would probably just have a single record, since it's just a set of flags.
Then the PartialRenderings model would basically be empty, because all you'll be doing is checking boolean values.
Finally, the partial_renderings table could be structured like this:
id | show_hometown | show_phone_number | show_real_name | ...etc...
--------------------------------------------------------------------
1 | true | false | false | ...
If partial rendering is on a PER-USER basis, then the partial_renderings table would need an additional user_id field to tie it to a given user, and therefore allow users to decide which things get rendered, and which don't. In this case you'd have more than a single record - you'd have one per user.

How to implement multiple selection on Rails 3

I have an index where I'm showing a list of documents. I would like to implement a multiple select in order to do different actions to the documents the user has selected
I have created a
<%= check_box_tag 'id', 'document.id %>
for each document, inside a form_tag
But if I select multiple checkboxes, the params that are passed to the action are overwrited and I'm just receiving the id of the last checkbox I've selected in the id param.
¿Anyone knows how to implement multiple select?¿Any other approach?
I'm running Rails 3 and Ruby 1.8.7
Thanks in advance
You need to set :multiple => true
<%= check_box_tag 'id', document.id, :multitple => true %>
This will give you results in form of an array in params[:id]
Minor correction (plural):
<%= check_box_tag 'ids[]', document.id %>
ensure your model is properly set for attr_accessible something like :document_ids

How do I access an instance variable from another controller?

So I have two models & controllers. Projects and Designers.
In my designers index view, I want it to show a list of all the projects that the designer has.
However, when I do a simple query like this:
<% #projects.each do |project| %>
<tr>
<td><%= link_to 'Show', project %></td>
<td><%= link_to 'Edit', edit_project_path(project) %></td>
<td><%= link_to 'Destroy', project, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
From the index.html.erb in the Designers view, it gives me the following error:
NoMethodError in Designers#index
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each
However, when I run that EXACT code from the index.html.erb file in the projects view, it works perfectly.
So how am I able to access that controller or at least data from the view of another controller? Do I have to add a projects variable (where it queries the db) to my index object in my designers controller?
Thanks.
UPDATED TO USE A SINGLE DESIGNER RECORD
You should use associations. Add this to your models.
class Designer < ActiveRecord::Base
has_many :projects
end
class Project < ActiveRecord::Base
belongs_to :designer
end
Your view should look like this:
<% #designer.projects.each do |project| %>
<% end %>
More info on associations here:
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
Figured out one way to do it. All I had to do was add an instance variable in my designers controller:
#projects = Project.all
But...that's not very DRY. Does anyone have a more elegant 'DRY' solution, so if I want to access other variables in other controllers I can do that easily without having to re-create them in the current controller?
Thanks.
In your designers controller, you need to set the #projects instance variable to only those projects belonging to the signed in designer, correct?
You'll need something like this:
def index
#projects = Project.where(:user_id => where ever you've stored your userid)
end
I hope this helps.