Setting Symbols in Form View - Ruby on Rails - ruby-on-rails

I am having problems trying to set symbol values in a form view. My view has a couple instance variables being used, #task and #team, #team is the one im having issues with. Tasks have a :team value that needs to be set. In this view #team holds a value, but when I hit the "Create" button and make a post, the #team value is lost, and #task contains no team value.
Here is the view I'm dealing with:
Note: the ":team => #task.team" line doesn't work
<% form_for(#task) do |f| %>
<%= f.error_messages %>
<% #task.team = Team.find(#team) %>
<p><%= #task.team.title%></p>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<p>
<%= f.label :hours %><br />
<%= f.text_field :hours %>
</p>
<p>
<%= f.label :team %><br />
<% :team => #task.team %>
</p>
<p>
<%= f.submit 'Create'%>
</p>
<% end %>
The Post method that gets called on Create:
def create
#task = Task.new(params[:task])
respond_to do |format|
if #task.save
format.html { redirect_to(#task, :notice => 'Task was successfully created.') }
format.xml { render :xml => #task, :status => :created, :location => #task }
else
format.html { render :action => "new" }
format.xml { render :xml => #task.errors, :status => :unprocessable_entity }
end
end
end

#Jordinl is right when he mentions that you could use a hidden form field. You can also automatically scope the task to the team in the controller by doing something like
#team = Team.find(params[:team])
and then
#team.tasks << Task.new(params[:task])
You'll need to have a has_many association set up in the team model for tasks
has_many :tasks
for this to work. Each task will also need the team id as well but it sounds like you already have that.

Why don't you set it as a hidden field?
<%= f.hidden_field :team, :value => #task.team %>

Related

Access to a param in another controller sended by render :template

So im sending a param from a view to a view of another controller
<%= render template: 'dishes/new', :id => #restaurant.id %>
and this is my other controller view:
def new
#dish = Dish.new
#id = params[:id]
end
def create
#dish = Dish.new(dish_params)
respond_to do |format|
if #dish.save
format.html { redirect_to #restaurant, notice: 'dish was successfully created.' }
format.json { render action: 'show', status: :created, location: :restaurant }
else
format.html { render action: 'show', location: :restaurant }
format.json { render json: #restaurant.errors, status: :unprocessable_entity }
end
end
end
private
def dish_params
params.require(:dish).permit( :avatar, :name, :description, [:id])
end
and this is my view who calls the form:
#new.html.erb
<h1>Add a new dish</h1>
<%= render 'dishes/dish_form' %>
then here is the form:
<%= form_for #dish, :url => { :controller => "dishes", action_name => "create" } do |f| %>
<div class="field">
<%= f.label :dish_name %>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %>
<%= f.text_field :description %>
</div>
<div class="field">
<%= f.label :image %>
<%= f.file_field :avatar %>
</div>
<div class="actions">
<%= f.submit 'Add new dish' %>
</div>
<% end %>
but when i try to save it i got this error:
I think your problem comes in when you are expecting your render template: 'dishes/new' to hit your DishesController. That is not what is happening when you are calling the render.
What you're doing is telling rails to load into your current view the template for 'dishes/new', and you're passing 'dishes/new' a variable that it can access when rendering. You aren't sending a param to a controller.
If you want to keep the current set up you have right now, you can make it work with some tweaking.
I'm going to assume that your Dish model belongs to Restaurant, and therefore has restaurant_id as a column. If that is true, then you can add a hidden field to your form for dishes, called restaurant_id, and update your permitted params in your controller to allow the restaurant id to be set on the dish.
Your form would look like this:
<%= form_for #dish, :url => { :controller => "dishes", action_name => "create" } do |f| %>
<%= f.hidden_field :restaurant_id, value: id %>
...
<% end %>
Your permitted params in your controller would look like this:
def dish_params
params.require(:dish).permit(:avatar, :name, :description, :restaurant_id)
end
You can get more information on how the rails rendering is working here
The error is saying that your controller named Restaurants does not have an action named "Show".
One solution would be to add the Action with the name "Show" to the restaurant controller.
The other option may be that you actually created the action you wanted, but you named it something other than "Show".

Linking two models in a multi-model form

I have a nested multimodel form right now, using Users and Profiles.
Users has_one profile, and Profile belongs_to Users.
When the form is submitted, a new user is created, and a new profile is created, but they are not linked (this is the first obvious issue). The user's model has a profile_id row, and the profile's model has a user_id row.
Here is the code for the form:
<%= form_for(#user, :url => teams_path) do |f| %>
<p><%= f.label :email %><br />
<%= f.text_field :email %></p>
<p><%= f.label :password %><br />
<%= f.password_field :password %></p>
<p><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></p>
<%= f.hidden_field :role_id, :value => #role.id %></p>
<%= f.hidden_field :company_id, :value => current_user.company_id %></p>
<%= fields_for #user.profile do |profile_fields| %>
<div class="field">
<%= profile_fields.label :first_name %><br />
<%= profile_fields.text_field :first_name %>
</div>
<div class="field">
<%= profile_fields.label :last_name %><br />
<%= profile_fields.text_field :last_name %>
</div>
<% end %>
<p><%= f.submit "Sign up" %></p>
<% end %>
A second issue, is even though the username, and password are successfully created through the form for the user model, the hidden fields (role_id & company_id - which are also links to other models) are not created (even though they are part of the model) - the values are successfully shown in the HTML for those fields however.
Any help would be great!
As requested, the controller code:
def new
#user = User.new
#user.profile = Profile.new
#role = Role.find_by_name("Regular")
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #teams }
end
end
def create
#user = User.new(params[:user])
#profile = Profile.new(params[:profile])
respond_to do |format|
if #profile.save && #user.save
format.html { redirect_to (teams_path) }
format.xml { render :xml => #profile, :status => :created, :location => #profile }
else
format.html { render :action => "new" }
format.xml { render :xml => #profile.errors, :status => :unprocessable_entity }
end
end
end
To answer question number one, change the following:
#profile = Profile.new(params[:profile])
to
#profile = #user.profile.build(params[:profile]) #In the case of a has_many relationship
or
#profile = #user.build_profile(params[:profile]) #In the case of a has_one relationship
The build command builds a new profile with the user_id properly set.
For the second question, can you delete the query for Role and Company during the new action and instead assign those during the create action? This would remove the necessity of passing hidden parameters.

How do I display error messages for nested resource validations?

I'm creating a basic blog application and I'm running into issues displaying error messages when a user tries to submit a blank comment. Instead of getting a nice looking error message, an active record error message with the correct validation erorrs. Such as
ActiveRecord::RecordInvalid in CommentsController#create
Validation failed: Name can't be blank, Email can't be blank
In my article/show view I have the following code:
<%= form_for([#article, #article.comments.build]) do |f| %>
<%= render "shared/error_messages", :target => #article %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :body %><br />
<%= f.text_area :body %>
</div>
<p><%= f.submit %></p>
<% end %>
My error messages partial looks like this:
<% if target.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(target.errors.count, "error") %> prohibited this record from being saved:</h2>
<ul>
<% target.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
I know the answer is simple but I can't figure it out.
Create action in comments controller:
def create
#article = Article.find(params[:article_id])
#comment = #article.comments.build(params[:comment])
respond_to do |format|
if #comment.save
format.html { redirect_to(#article, :notice => 'Comment was successfully created.') }
format.xml { render :xml => #article, :status => :created, :location => #article }
else
format.html { render :action => "articles/show" }
format.xml { render :xml => #comment.errors, :status => :unprocessable_entity }
end
end
I had a similar problem. everything seemed to work fine, but I was not getting any errors
The solution i found is to build the comment in article#show instead of the view:
#article = Article.find(params[:id])
#comment = #article.comments.build(params[:comment])
and in your articles#show don't use #article.comments.build but #comment:
<%= form_for([#article, #comment]) do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<p><%= f.submit %></p>
<% end %>
make sure you build the comment in your comment#create as well (you really have no choice though :P)
also, I don't know if it matters (i'm pretty new to ruby), but I think you need to pass f.object instead of #comment.
I think you're saying that you get the big grey-on-white error page, right?
Check the backtrace, but I suspect that this is coming from the create action in the controller, not the view.
If your controller uses save! with the ! at the end, that means that it will raise an error if the record is invalid. save, on the other hand, returns true or false and lets you use simple branch logic to decide how to react.
If my hunch on save! isn't right, though, please post controller code so we can dig deeper :) Thanks!
The solution was to direct the comments created action back to the correct controller/action and target #comment in my error message partial.
Final view
<%= form_for([#article, #article.comments.build]) do |f| %>
<%= render "shared/error_messages", :target => #comment %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :body %><br />
<%= f.text_area :body %>
</div>
<p><%= f.submit %></p>
<% end %>
Final create action in comments controller
def create
#article = Article.find(params[:article_id])
#comment = #article.comments.build(params[:comment])
respond_to do |format|
if #comment.save
format.html { redirect_to(#article, :notice => 'Comment was successfully created.') }
format.xml { render :xml => #article, :status => :created, :location => #article }
else
format.html { render :action => "articles/show" }
format.xml { render :xml => #comment.errors, :status => :unprocessable_entity }
end
end

How to use a nested form for multiple models in one form?

I'm struggling to come up with the proper way to design a form that will allow me to input data for two different models. The form is for an 'Incident', which has the following relationships:
belongs_to :customer
belongs_to :user
has_one :incident_status
has_many :incident_notes
accepts_nested_attributes_for :incident_notes, :allow_destroy => false
So an incident is assigned to a 'Customer' and a 'User', and the user is able to add 'Notes' to the incident. I'm having trouble with the notes part of the form. Here how the form is being submitted:
{"commit"=>"Create",
"authenticity_token"=>"ECH5Ziv7JAuzs53kt5m/njT9w39UJhfJEs2x0Ms2NA0=",
"customer_id"=>"4",
"incident"=>{"title"=>"Something bad",
"incident_status_id"=>"2",
"user_id"=>"2",
"other_id"=>"AAA01-042310-001",
"incident_note"=>{"note"=>"This is a note"}}}
It appears to be attempting to add the incident_note as a field under 'Incident', rather than creating a new entry in the incident_note table with an incident_id foreign key linking back to the incident.
Here is the 'IncidentNote' model:
belongs_to :incident
belongs_to :user
Here is the form for 'Incident':
<% form_for([#customer,#incident]) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :other_id, "ID" %><br />
<%= f.text_field :capc_id %>
</p>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<p>
<%= label_tag 'user', 'Assign to user?' %>
<%= f.select :user_id, #users.collect {|u| [u.name, u.id]} %>
</p>
<p>
<%= f.label :incident_status, 'Status?' %>
<%= f.select :incident_status_id, #statuses.collect {|s| [s.name, s.id]} %>
</p>
<p>
<% f.fields_for :incident_note do |inote_form| %>
<%= inote_form.label :note, 'Add a Note' %>
<%= inote_form.text_area :note, :cols => 40, :rows => 20 %>
<% end %>
</p>
<p>
<%= f.submit "Create" %>
</p>
<% end %>
And finally, here are the incident_controller entries for New and Create.
New:
def new
#customer = current_user.customer
#incident = Incident.new
#users = #customer.users
#statuses = IncidentStatus.find(:all)
#incident_note = IncidentNote.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #incident }
end
end
Create:
def create
#users = #customer.users
#statuses = IncidentStatus.find(:all)
#incident = Incident.new(params[:incident])
#incident.customer = #customer
#incident_note = #incident.incident_note.build(params[:incident_note])
#incident_note.user = current_user
respond_to do |format|
if #incident.save
flash[:notice] = 'Incident was successfully created.'
format.html { redirect_to(#incident) }
format.xml { render :xml => #incident, :status => :created, :location => #incident }
else
format.html { render :action => "new" }
format.xml { render :xml => #incident.errors, :status => :unprocessable_entity }
end
end
end
I'm not really sure where to look at this point. I'm sure it's just a limitation of my current Rails skill (I don't know much). So if anyone can point me in the right direction I would be very appreciative. Please let me know if more information is needed!
Thanks!
Check api for fields_for method and scroll to one-to-many section.
Your model has many :incident_notes, not one incident_note, that is why it doesn't understand relationship and tries to find a field with this name.
So it should be:
<% f.fields_for :incident_notes do |inote_form| %>
<%= inote_form.label :note, 'Add a Note' %>
<%= inote_form.text_area :note, :cols => 40, :rows => 20 %>
<% end %>
It iterates through all incident_notes assigned to incident and produces fields for each of them.
You also have to build at least one note in you new action, otherwise there will be none:
def new
#incident = Incident.new
#incident.incident_notes.build
# ...
end

Rails: has_many through association, and the form for creating new instances

I'm still super new with Rails, and just trying to get my first has_many through association set up.
Recipes have many ingredients, and each ingredient has an amount needed for the recipe. The ingredient_amount table has a recipe_id, an ingredient_id, and an amount.
When creating a new recipe, I want to be able to create these recipe/ingredient associations in the same place. In the end, I'm going to build an AJAX autocompleter for the ingredients. For now, as a baby step, I'd like to just assume the ingredient exists, and take care of checking once I've got this part down.
So, how can I make new.html.erb for recipes do this? How can I extend the form for more than one ingredient?
As it stands now, after going through http://weblog.rubyonrails.org/2009/1/26/nested-model-forms
I still can't get any fields to add ingredients. The current code is below.
class Recipe < ActiveRecord::Base
has_many :ingredient_amounts
has_many :ingredients, :through => :ingredient_amounts
accepts_nested_attributes_for :ingredient_amounts, :allow_destroy => true
end
class IngredientAmount < ActiveRecord::Base
belongs_to :ingredient
belongs_to :recipe
end
class Ingredient < ActiveRecord::Base
has_many :ingredient_amounts
has_many :recipes :through => :ingredient_amounts
end
Here's new.html.erb as I have it currently:
<h1>New recipe</h1>
<% form_for #recipe do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :instructions %><br />
<%= f.text_area :instructions %>
</p>
<p>
<%= f.label :numberOfServings %><br />
<%= f.text_field :numberOfServings %>
</p>
<p>
<%= f.label :prepTime %><br />
<%= f.text_field :prepTime %>
</p>
<p>
<% f.fields_for :ingredient_amounts do |ingredient_form| %>
<%= ingredient_form.label :ingredient_formedient_id, 'Ingredient' %>
<%= ingredient_form.collection_select :ingredient_id, Ingredient.all, :id, :name, :prompt => "Select an Ingredient"%>
<%= ingredient_form.text_field :amount %>
<% unless ingredient_form.object.new_record? %>
<%= ingredient_form.label :_delete, 'Remove:' %>
<%= ingredient_form.check_box :_delete %>
<% end %>
</p>
<% end %>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
<%= link_to 'Back', recipes_path %>
The important bits of the recipe controller:
def new
#recipe = Recipe.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #recipe }
end
end
def create
#recipe = Recipe.new(params[:recipe])
respond_to do |format|
if #recipe.save
flash[:notice] = 'Recipe was successfully created.'
format.html { redirect_to(#recipe) }
format.xml { render :xml => #recipe, :status => :created, :location => #recipe }
else
format.html { render :action => "new" }
format.xml { render :xml => #recipe.errors, :status => :unprocessable_entity }
end
end
end
And... I have no idea where to start in the ingredient_amounts controller.
This was my very first stab, and I'm pretty sure it's not so close :)
def new
#recipe = Recipe.find(params[:recipe_id])
#ingredient = Ingredient.find(params[:ingredient_id])
#ingredient_amount = Recipe.ingredient_amounts.build
end
Thanks for the help!
I believe what you are looking for is 'Nested Model Forms'.
Try this link: http://weblog.rubyonrails.org/2009/1/26/nested-model-forms
It's hard to know what to search for when you dont really know the terminology to begin with :)

Resources