rails 3 select control from nested models - ruby-on-rails-3

I have 2 models user and team. a team can have many users each users belong to a team.
team_id is a column in my user table as a fk.
I want to have a select drop down on my create user form that has all my teams team_id in it.
This code does what I want BUT
<%= f.fields_for :teams do |builder| %>
<p>
<%= f.label :team_id, "Select Team For User" %>
<%= builder.collection_select :team_initials, Team.all, :id, :team_initials %>
</p>
<% end %>
it does not try to add the id value to a user. here is the error
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"xxxxx",
"user"=>{"name"=>"brand new",
"email"=>"test1#test.com",
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]",
"teams"=>{"team_initials"=>"27"}},
"commit"=>"Create my account"}
It complains that it cant add to the team model.
All I want to do is grab the ID of all existing teams for my create user form so when you crate a user you can select that users team.
The reason I have team_initials above is I was trying to use a more user friendly field for select but still user team Id as the value.

I think you're on the right track. The fields_for mechanism is for setting values in the associated model. I think all you're trying to do is make the association.
So you can lose the fields_for line and then this section:
builder.collection_select :team_initials, Team.all, :id, :team_initials
Should be:
f.collection_select :team_id, Team.all, :id, :team_initials
I'm looking here for my info on collection_select since I don't know it off the top of my head:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html
I think this will change this parameter from "teams"=>{"team_initials"=>"27"}}, to "team_id"=>"27",
I hope that fixes it.

Related

Using a 'new' form to make database changes

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])

Accessing attributes from different associated models rails 3

I am looking to get a better understanding of Active Model/Record relationships and how to call attributes dependent upon where the attributes are located (models) and where I am calling them. So for example I can access the attribute dish_name from within the recipe controller like so
def all_recipes
#recipes = Recipe.all
end
In the view
<% #recipes.each do |r| %>
<%= r.dish_name %>
<% end %>
Now say i want to access a recipe attribute from within my controller called worldrecipes and i have just written a method that returns all recipes with the same country. a country has many recipes as a relation
So my method is
def self.top_countries
joins(:recipes).
select('countries.*, count(*) AS recipes_count').
group('countries.id').
order('recipes_count DESC')
end
My controller
#worldrecipes = Country.where(:name => params[:name])
and view
<% #worldrecipes.each do |r| %>
<%= r.name %>
<% end %>
so accessing the country name attribute is easy as its in the country model and thats where my query results are being returned from (I think)...My question is how do i access the dish_name attribute from my recipe model to that links to the country name
Hope that makes sense, does anyone have a guide on how to work this out or some golden rules for this
Thank you
I think what you need is:
#country=Country.where(:name=>params[:name]).first
#worldrecipes=#country.recipes
And in the view:
<% #worldrecipes.each do |r| %>
<%= r.dish_name %>
<% end %>
This would print the dish names of the recipes of the country with name provided by params[:name]
EDIT:
Ok Let me clear this up for you :)
Your model relationship is setup such that each country has many recipes. i.e a country has many recipes.
So you have,
has_many :recipes
in country.rb and
belongs_to :country
in recipe.rb
Now when you want to access all the recipes belonging to a country, what you do is, you call country_record.recipes (country_record being the object of the country record you need).
And when you call,
Country.where(:name=>params[:name])
What you actually get is the active record object representing the COUNTRY itself and not the recipes of the country and that is why Italy was printed.
Hope this helped you.
For starters you want to make sure you have the association setup in your models:
country.rb
class Country < ActiveRecord::Base
has_many :recipes
end
recipe.rb
class Recipe < ActiveRecord::Base
belongs_to :country
end
If you haven't already done so, add a foreign_key attribute to your recipe model by running the following migration:
rails g migration add_country_id_to_recipe country_id:integer
Now that your associations are in place you can easily query for a countries respective recipes. In your controller:
#worldrecipes = Country.where(:name => params[:name])
Then in your view:
<% #worldrecipes.each do |c| %>
<% c.recipes.each do |r| %>
<%= r.dish_name %>
<% end %>
<% end %>
In regards to 'golden rules' I highly recommend you check out Association Basics. This is the go-to place for an overview of what you can do with associations.

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 %>

Rails 3: trying to follow railscast #17 to add genres to my posts

I've followed along exactly like the Railscast describes but using "genre" instead of "category," but whenever I make a post the genre_id shows as NULL and I'm getting a WARNING: can't mass assign attribute genre_ids
I only had genre_id in my post model attr_accessible because that's the name of the attribute, however when I change it to genre_ids. I get the error
ActiveRecord::StatementInvalid in PostsController#create Could not find table 'genres_posts'
post form
<% for genre in Genre.find(:all) %>
<div>
<%= check_box_tag "post[genre_ids][]", genre.id, #post.genre.include?(genre) %>
<%= genre.name %>
</div>
<% end %>
post model
class Post < ActiveRecord::Base
has_and_belongs_to_many :genres
end
I don't have an answer, but here are the things you should check:
In your code, the line <%= check_box_tag "post[genre_ids][]", genre.id, #post.genre.include?(genre) %> should include genres, not genre:
<%= check_box_tag "post[genre_ids][]", genre.id, #post.genres.include?(genre) %>
What Ryan Bates (I love his webcast) doesn't tell is that you need changes on your database so that your models may be stored. The reason for that is, that on a relational database, a m:n relation is normally realized by a separate table that just stores that relation only. Have a look at the "Rails Guides: Has and belongs to many associations".
So you have to generate a standalone migration (see the Rails Guide for that) that creates that table that hold both ids to posts and genres in one table. The table should be named therefore genres_posts, and include the columns genre_id and post_id.
So depending on what you have done before, you may follow all the steps to reach a working example application. Good luck!

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