Rails form not creating object - ruby-on-rails

I have created a simple form to create an instance of a modle and for some reason it is not calling the create method in the controller. Here is the form code:
<% #house.mates.each do |mate| %>
<p><%= mate.name %></p>
<% end %>
<h2>Add a new mate:</h2>
<%= form_for #mate do |f| %>
<p><%= f.label "Name" %>
<%= f.text_field :name %>
<%= f.hidden_field :house_id %>
</p>
<%= f.submit "Submit", :action => :create %>
<% end %>
Here is the controller code:
class MatesController < ApplicationController
def new
#mate = Mate.new
end
def create
#mate = Mate.new(params[:mate])
#mate.save
redirect_to house_path(current_house)
end
end
There is a many to one relationship between the Mate model and the House model... I am fairly new to rails but I have made other apps with similar forms, and I have never had this problem before. I can create and save Mate objects in the console, and I am not getting any errors, so it seem that somehow the controller method is not being called. Any help is much appreciated!

In fact, if other things have no problem, your #mate object should be created. You just can't see it in house page because you have not associated #mate with house in your code.
In your form you referred :house_id, but this attribute is nil when you rendering the form.
The reason is you have not assigned it in controller.
In controller you need to initialize #mate from house object to have house_id inside it
def new
#house = something
#mate = #house.mates.new # Instead of Mate.new
end

Related

Wrong action called when using Partial

I’m trying to use Partial to render a form into Edit and Create view (to handle both actions). The problem is that it works with Create action but the form does not work for editing, it only creates. It seems that the app ignore and use create action by default (the submit button is automatically named “Create Expense” instead of “Update Expense”).
By using this kind of route, I want to edit an Expense (that is linked with a Category).
I did the navigation from Category show view to my Expense edit form view like this.
<% #category.expenses.each do |expense| %>
<tr>
<td><%= expense.name %></td>
<td>
<%= link_to "Edit", edit_category_expense_path(#category, expense) %>
</td>
</tr>
<% end %>
I’m using Partial for rendering my form into Expense edit view.
<h1>Edit Expenses</h1>
<%= render "form", expense: #expense %>
Then my form is simply like this.
<%= form_with model: [ #category, #expense] do |form| %>
<p>
<%= form.label :name %><br>
<%= form.text_field :name %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
My Expense controller
def edit
#expense = Expense.find(params[:id])
#category = #expense.category
end
def new
#expense = #category.expenses.new
end
Finally, i'm rendering the creation form in my Category show view.
<h2>Add Expense:</h2>
<%= render 'expenses/form' %>
But I got undefined method 'model_name' for nil:NilClass when I'm trying to access to my Category show view
Solution based on #Chiperific answer
According to my project structure, I had to put #expense = Expense.new in the show action of Category controller. That's where I displayed the form.
As for the edit form, the answer of #Chiperific explains it perfectly
Thanks
.build instantiates a new record. Rails recognizes that the record is new, not persisted, and automatically does what you are seeing (send the form data to the #new action and use 'Create' for the button language.
In your controller, you need to get the existing record you want to edit:
...
def new
#expense = #category.expenses.new
end
def edit
#expense = Expense.find(params[:id])
end
And adjust your form:
<%= form_with model: [ #category, expense ] do |form| %>
...

edit form inputs not appearing for non-persisted data

I have an edit form that is not a devise form (i have a devise edit on a different view) to edit a users details. However the form inputs only appear if the data is already there. So a user is unable to add new details to the form, as the inputs don't appear at all.
Is this happening as i'm not using a devise form view?
This is the code in my own edit file:
<%= render "devise/registrations/details", f: f, resource: #resource, addressable: #resource, default_location: nil %>
Then in the devise/registration/details i have this:
<%= f.simple_fields_for :address do |fields| %>
<%= render "address/fields", fields: fields, addressable: addressable, resource: resource %>
<% end %>
However, i think the inputs are not showing up as fields are blank in the iteration. However these fields are showing up in the actual devise/edit file, even if they are blank, just not in my new one.
When using fields_for and simple_fields_for (which is basically just a pimped up version of the former) you have to "seed" the inputs in order for them to appear.
Consider this simplified plain rails example:
class UsersController < ApplicationController
def new
#user = User.new
#user.build_address
end
# ...
end
<%= simple_form_for(#user) do |f| %>
<%= f.simple_fields_for(:address) do |af| %>
<%= af.input :street %>
<% end %>
<% end %>
If we remove the line #user.build_address there will be no nested inputs. Thats because simple_fields_for calls the method #address on #user and creates inputs for the record. If the association is one or many to many it would iterate through the association. If the method returns nil or empty there are no inputs to create - it would be like calling form_for with nil.
You can also pass a second argument to fields_for to manually specify the record object:
<%= simple_form_for(#user) do |f| %>
<%= f.simple_fields_for(:address, #user.address || #user.build_address) do |af| %>
<%= af.input :street %>
<% end %>
<% end %>
In Devise you can do this by passing a block to super or by overriding #build_resource.
class MyRegistationsController < Devise::RegistrationsController
def new
super { |resource| resource.build_address }
end
end

Rails: form_for active record object complaining about no index path

I have a survey model that has no index page. I only want an edit view for this model, but it seems like rails wont let me do that. It complains undefined method surveys_path when I try to use form_for(#survey). Is there anyway around doing this without creating an empty index route/view.
Here is my survey controller so far
class SurveysController < ApplicationController
def show
#survey = Survey.find(params[:id])
end
def edit
#survey = Survey.new
job = Job.find(params[:id])
#survey.job_id = job.id
authorized_user = job.user
unless !is_runner?(current_login) && current_login.id == authorized_user.id
redirect_to jobs_path
end
end
def update
#survey = Survey.new(params[:survey])
end
end
And here is the form partial being rendered in the edit.html.erb
<%= form_for(#survey) do |f| %>
<div class="field">
<%= f.label :speed %><br />
<%= f.text_field :speed %>
</div>
<div class="field">
<%= f.label :service %><br />
<%= f.text_field :service %>
</div>
<div class="field">
<%= f.label :suggestion %><br />
<%= f.text_area :suggestion %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
It shouldn't be asking about surveys_path just for defining a form, but there are some oddities in your controller code that could be causing you grief.
Your edit action should, in the surveys controller of a RESTful app, be using that params[:id] to find an existing survey, why is it finding a job? It should be doing the same as your show action.
Your survey object in the survey edit method is new and unsaved, therefore the form builder will generate a form pointing to a create action rather than an update action. Form builder will generate an edit form only for records that are persisted?
Have you defined the routes for this model? You should have something like the following in your routes file:
resources :surveys, :except => [:index] # will create all rest routes for survey model except for an index route.
You get this error if you mistakenly run your model/table as plural instead of singular. You probably ran something like this:
rails generate model surveys
Instead of this:
rails generate model survey
So, if you run:
rake routes
You'll probably see that all of your routes have an 's' ie. surveys_new.
So, rails is confused. You need to rename your table in a migration.
class ChangePluralNametoSingularforSurveys< ActiveRecord:Migration
def change
rename_table :surveys, :survey
end
end
Then you'll have to rename your files (surveys.rb, etc) manually.
For me, the issue was nested routes. If your object has a parent and its routes are nested, you'll need to do something like:
<%= form_for([#category, #survey]) do |f| %>
...
<% end %>

checkboxtag in forms

Im looking for the following thing: an array of all users (only 6 in this case) with a checkbox in front of their name, resulting in a list of selectable players for the game.
Current code:
<%= form_for #game, url: games_path, :method => "post" do |f| %>
<%= f.label :name %>
<%= f.text_field :name, :value => "#{current_user.name}\'s Game" %>
<%= f.fields_for :participants do |ff| %>
<%= ff.label :user_id %>
<%= ff.text_field :user_id %>
<%= ff.check_box :user_id %>
<% end %>
<%= f.submit "Create Game", class: "btn btn-primary" %>
<% end %>
I'm now having 3.times { #game.participants.build } in my controller which effectively gives me 3 textfields in which i can fill in the participant id in order to make a record in the table participants (which is linked to games).
I've been looking around for 1.5h now and i cant seem to find a proper answer. What i need is a syntax that gives me a list of all current users (say #users) with a checkbox attached to it. When I click the checkbox it should add its id to the parameters and i should be able to create a new game with the linked participant id's. However I'm getting some problems with the ID's attached to the check_box which always seems to be 1. I've read some stuff about checkboxes being a pain with hashes, but I have no other solution atm.
I tried:
<% #users.each do |i| %>
<%= check_box_tag "alternate_numbers[#{i}]" %> <%= i.name %><br />
<% end %>
But i see no way to get that fixed up part of the form itself.
GamesController code (edit):
def new
#users = User.paginate(page: params[:page])
#games = current_user.games
#game = Game.new
3.times { #game.participants.build }
end
def create
#game = Game.new(params[:game])
#newround = #game.rounds.new
#newround.storyFragment = "New story!"
if #game.save && #newround.save
flash[:success] = "Created!"
redirect_to game_path(#game.id)
else
redirect_to root_url
end
end
It's very vague to describe since im not exactly sure how to accomplish this.
In short: the check_box should contain the value of the user_id in the loop. I'm now filling in a manual ID with the text_field helper but i'd like to have the checkbox linked to the username that is right next to it in the view.
Any guidelines/solutions/tips?
Thx
Okay, so you're making a form for a new Game. You now have to feed that new Game, along with some Participants to your view.
def new
#game = Game.new
#participants = User.all # or the users you want
end
Now use those in your view. You were on the right track. Depending on how your create action works:
<% #participants.each do |p| %>
<%= check_box_tag "participants[#{p.id}]" %> <%= p.name %>
<% end %>
I think what you were missing was the documentation for check_box_tag. The input attribute name is the argument.
You also seem to have a lot of logic in your controllers. Remember to keep the logic in the models, and only use the controllers to give the right objects to your views, and taking them for saving, for example. As the saying goes, "fat model, skinny controller".

Adding a user_id to a Message model

I currently have a simple app that includes user authentication through devise and a message model(the message model uses Jquery and Faye). Both are working fine independently, but I would like to add a user_id to the messages.
I have already updated the schema and models with the relationship, but I am having trouble inputting the necessary code to have the view and controller input the relationship into the db, while keeping the jquery working. I wasn't sure of the best way, but here I tried to create a hidden field that would pull the user_id, not sure if this is even possible. Here is the applicable code, any help is appreciated.
Message index.html.erb
<ul id="chat">
<%= render #messages %>
</ul>
<%= form_for Message.new, :remote => true do |f| %>
<div class="field">
<%= f.text_field :content %>
</div>
<div class="field">
<%= f.hidden_field :user_id %>
</div>
<div class="actions">
<%= f.submit "Send" %>
</div>
<% end %>
create.js.erb for messages
<% broadcast "/messages" do %>
$("#chat").append("<%= escape_javascript render(#user.message) %>");
<% end %>
$("#new_message")[0].reset();
Messages Controller
class MessagesController < ApplicationController
def index
if #authentications = current_user
#messages = Message.all
else
redirect_to authentications_url
flash[:notice] = "You need to sign in before answering questions"
end
end
def create
#user = User.find(params[:user_id])
#message = #user.message.create(params[:message])
end
end
I think you have everything you would need, but if not, let me know and I will be happy to provide it for you.
Thanks, everyone.
two things to correct,
1)use user association to create message instance in form(probably current_user if logged-in user create a message)
<%= form_for user.messages.new, :remote => true do |f| %> #// assuming its has many association
2) if it is has_many association then change association in create action
#message = #user.messages.create(params[:message])

Resources