I'm new to Rails and am trying to create a view form_for which adds data in two different models. I've looked at stack overflow posts about multiple models, and I've used a fields_for call to submit the information to the second model. However, my form submission only processes the form_for data, and not the fields_for. Please advise on how I would fix this. My two models are for users and schools (with the goal of someone registering their school and their own information, then being able to log in and attach that school to that adviser)
View code:
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#user) do |f| %>
<%= fields_for(#school, :url => {:controller => "advisers",
:action => "new_school"}) do |s| %>
... fields...
<% end %>
<legend>Primary Adviser Information</legend>
... forms ...
<%= f.hidden_field :access_level, :value => "Adviser" %>
<p> </p>
<div class="col-md-12">
<%= f.submit "Register", class: "btn btn-primary" %>
</div>
<% end %>
</div>
</div>
</div>
Advisers Controller:
def new
#user = User.new
#school = School.new
end
def new_school
#school = School.new(school_params)
#school.save
end
Routes:
resources :advisers do
collection do
post :new_school
end
end
Output:
Started POST "/users" for 24.13.7.99 at 2015-07-16 19:41:37 +0000
Processing by UsersController#create as HTML
Parameters: (params here)
(0.1ms) begin transaction
(inserts user here)
(17.1ms) commit transaction
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 6]]
Redirected to https://pennmc2-mdmorant.c9.io/adviser
Notice that it only activates the User post but not the advisers post.
Use accept_nested_attributes_for inside on of your models - Advisor/User? like this
accepts_nested_attributes_for :school
Getting fields_for and accepts_nested_attributes_for to work with a belongs_to relationship
Related
Sorry for the vague title.
I want to enable comments on a post / comments type system (in my case snags and snag comments).
I have a snags table, a snag_comments table and a has many / belongs to relationship between snag and snag comments.
On the show page for each snag I have a form rendering for snag comments. When I submit the form, it redirects to the root url and doesn't save anything to the snag_comments table.
This is all the information I get:
Started POST "/snag_comments" for ::1 at 2019-05-07 12:53:16 +0100
Processing by SnagCommentsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"yBefFfnI289UXqQYzF37DBRGQSk2Uqu41/OQO/mnET9aj2S3OqjLmSGtgyyZkTDz0aSdKzSPofQNeSzx/UH3ng==", "snag_comment"=>{"snag_id"=>"183", "content"=>"sdfgfsdgsdfgds"}, "commit"=>"Send"}
Resident Load (0.3ms) SELECT "residents".* FROM "residents" WHERE "residents"."id" = $1 ORDER BY "residents"."id" ASC LIMIT $2 [["id", 2], ["LIMIT", 1]]
Redirected to http://localhost:3000/
Filter chain halted as :redirect_residents rendered or redirected
So my params are going through. I don't know why it's not saving to the database.
In my snags controller I have:
def show
#snag_attachments = #snag.snag_attachments.all
#snag_comment = SnagComment.new
#snag_comments = SnagComment.where(snag_id: #snag.id)
end
And my snag comments controller (which is currently incomplete while I figure out this broken part):
class SnagCommentsController < ApplicationController
skip_authorization_check
before_action :set_parent
def create
#snag_comment = SnagComment.new(snag_comment_params)
if #snag_comment.save
redirect_to snags_path
end
end
private
def set_parent
#parent = #snag
end
def snag_comment_params
params.require(:snag_comment).permit(:content, :image, :snag_id,
:commenter, :first_name, :last_name)
end
end
The form which is rendered (views/snag_comments/_form):
<div class="snag-comment-form">
<%= simple_form_for snag_comment, url: snag_comments_path do |f| %>
<% if snag_comment.errors.any? %>
<div class="submission-errors">
<ul>
<% snag_comment.errors.full_messages.each do |error_msg| %>
<li>
<%= fa_icon "exclamation-circle" %>
<%= error_msg %>
</li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :snag_id, value: #snag.id %>
<%= f.input :content, label: false, as: :text, placeholder: t(".content"), maxlength: 1000, required: true, class: "snag-comment-content" %>
<div class="snag-comment-submit">
<%= f.submit t(".send"), class: "btn branded-btn send" %>
</div>
<% end %>
</div>
And where the form is called from (views/homeowners/snags/show):
<%= render 'snag_comments/form', snag_comment: #snag_comment %>
I need the snag comments to be outside of the homeowner module because it also needs to be accessible to the admin module (admin and homeowner can comment on the same snags).
I can't figure out why the form is redirecting and not saving. I have tried removing any redirect and just specifying that the form should be saved but it still redirects to root url and doesn't save, so something must be going wrote between passing the params and actually saving.
You seem to have missed the most basic fundamental on how to setup a nested resource - nesting the route:
resources :snags do
resources :snag_comments
end
This will make the "parent-child" relation part of the RESTful route and make it very clear what is going on VS implicitly passing that information in the form body.
class SnagCommentsController < ApplicationController
# ...
before_action :set_snag
# POST /snags/:snag_id/snag_comments
def create
#snag_comment = #snag.comments.new(snag_comment_params)
if #snag_comment.save
redirect_to #snag, notice: 'Comment created'
else
render :new
end
end
private
def set_snag
#snag = Snag.find(params[:snag_id])
end
def snag_comment_params
params.require(:snag_comment)
.permit(:content, :image,:commenter, :first_name, :last_name)
end
end
To create a form that posts to the nested route use an array:
def show
#snag_attachments = #snag.snag_attachments
#snag_comment = #snag.comments.new
#snag_comments = #snag.comments
end
<%= simple_form_for([#snag, #snag_comment]) do |f| %>
# ...
<% end %>
Make sure you remove the input for the parent ID. It is explicitly passed as segment in the URL.
I'm trying to save a form, and I am so lost on why it refuses to save. Does anybod have a clue what might be wrong?
Here's the form code:
<%= form_for #service, url: services_path do |f| %>
<% #profiles.each do |profile| %>
<%= f.text_field :service_id, value: "#{profile.service_id}" %>
<div class="media">
<a class="media-left" href="#">
<%= image_tag profile.avatar, height: '45', width: '45', class: 'img-circle' %>
</a>
<div class="media-body">
<h4 class="media-heading"><%= profile.service_username %></h4>
<%= profile.service %>
</div>
</div>
<% end %>
<%= f.submit %>
<% end %>
and
#service = current_user.services.new
the association between them are:
user has_many :services
service belongs_to :user
and the services controller create looks like this:
def create
#service = current_user.services.new(service_params)
if #service.save
flash[:notice] = "success"
redirect_to root_url
else
flash[:alert] = "Unable to add"
redirect_to :back
end
end
my logs say:
Started POST "/services" for 127.0.0.1 at 2015-01-17 18:09:44 -0800
Processing by ServicesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"lsW5aVuVUCQrHsaCo+uxbR11sF3mph3lTnM8O/Dtxn8=", "service"=> {"service_id"=>"2967861508"}, "commit"=>"Create Service"}
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = 30 ORDER BY "users"."id" ASC LIMIT 1
(0.2ms) BEGIN
(0.2ms) ROLLBACK
Redirected to http://localhost:3000/schedules
Completed 302 Found in 9ms (ActiveRecord: 1.1ms)
Oops, minor edit below (#service.errors instead of #validation.errors):
From your logs, you can see that you got into the controller create method and the save failed. This is usually a validation problem but I can't tell from what you posted. I would put #service.errors into the flash instead of just "unable to add". This should help you and future users see what's going on when the create fails.
I am making a rails application. After a user has registered (I have
already created user registration with devise), they can fill out this
form that will contain their profile information. The form should
submit a post request to the create action in the informations controller, but for some reason I can't configure the routes properly. When i run rake routes, for informations#create, which is what the form should be going to, it has a blank path. There is also informations#index, which is what I guess its going to now. How do I get the form to go to informations#create if the path is blank? I have done this several times, and i can't find what is wrong. Here is the model:
class Information < ActiveRecord::Base
belongs_to :user
end
Here is the controller:
class InformationsController < ApplicationController
def new
#information = Information.new
end
def create
#information = Information.create(params[:information])
redirect_to student_path
end
def index
end
end
And here is the view for the new action.
<div class="span6 offset3 text-center">
<h1>Edit your information</h1>
<%= simple_form_for #information do |f| %>
<%= f.input :skills %>
<%= f.input :looking_for, :label => 'What help do you need?' %>
<%= f.input :my_idea %>
<%= submit_tag "Save", :class => "btn btn-primary btn-large" %>
<% end %>
</div>
Here is the line in the routes file:
resources :informations
I get the following error:
undefined method `information_index_path' for #<#:0x007f9c00c7b3e0>
Here is rake routes for the files
informations GET /informations(.:format) informations#index
POST /informations(.:format) informations#create
Here is my full stacktrace when trying to load the page that shows the form:
Started GET "/informations/new" for 127.0.0.1 at 2013-10-21 17:25:09 -0400
Processing by InformationsController#new as HTML
Rendered informations/new.html.erb within layouts/application (64.2ms)
Completed 500 Internal Server Error in 70ms
ActionView::Template::Error (undefined method `information_index_path' for #<#<Class:0x007ff03e8b34a0>:0x007ff03e8b23e8>):
2: <div class="span6 offset3 text-center">
3: <h1>Edit your information</h1>
4:
5: <% simple_form_for #information do |f| %>
6: <%= f.input :skills %>
7:
8:
app/views/informations/new.html.erb:5:in `_app_views_informations_new_html_erb__3172218935119285240_70334909089600'
Rendered /usr/local/rvm/gems/ruby-2.0.0-p247#firehose/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.0ms)
Rendered /usr/local/rvm/gems/ruby-2.0.0-p247#firehose/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (0.7ms)
Rendered /usr/local/rvm/gems/ruby-2.0.0-p247#firehose/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/template_error.erb within rescues/layout (9.1ms)
Started GET "/informations/new" for 127.0.0.1 at 2013-10-21 17:25:09 -0400
Processing by InformationsController#new as HTML
Rendered informations/new.html.erb within layouts/application (8.3ms)
Completed 500 Internal Server Error in 13ms
ActionView::Template::Error (undefined method `information_index_path' for #<#<Class:0x007ff03e8b34a0>:0x007ff03e8708a8>):
2: <div class="span6 offset3 text-center">
3: <h1>Edit your information</h1>
4:
5: <% simple_form_for #information do |f| %>
6: <%= f.input :skills %>
7:
8:
app/views/informations/new.html.erb:5:in `_app_views_informations_new_html_erb__3172218935119285240_70334908978600'
Rendered /usr/local/rvm/gems/ruby-2.0.0-p247#firehose/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.0ms)
Rendered /usr/local/rvm/gems/ruby-2.0.0-p247#firehose/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.3ms)
Rendered /usr/local/rvm/gems/ruby-2.0.0-p247#firehose/gems/actionpack-4.0.0/lib/action_dispatch/middleware/templates/rescues/template_error.erb within rescues/layout (14.0ms)
Your problem is related to the fact that the word information is both the plural and the singular form. Just like water, or paper, or evidence. Rails considers those words uncountable.
There are two things you can do: either name your model something else or edit the file config/initializers/inflections.rb like so:
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.uncountable %w( information )
end
Your form should be for one single information object. Not for a collection of information objects. Note that i have changed simple_form_for #informations to simple_form_for #information
<div class="span6 offset3 text-center">
<h1>Edit your information</h1>
<% simple_form_for #information do |f| %>
<%= f.input :skills %>
<%= f.input :looking_for, :label => 'What help do you need?' %>
<%= f.input :my_idea %>
<%= submit_tag "Save", :class => "btn btn-primary btn-large" %>
<% end %>
</div>
Also your failure is not because rails didn't generate information_index_path. Its because the named route for information#index is informations_path. the path is generated wrongly because you are using collection of objects.
Not sure if this will help, but try adding a = in front of simple_form_for. so that it will have a <%= instead of <%
Fairly simple question, and I've seen lots of similar ones asked in my search, but none of the solutions I've read have worked so far. Not sure where I'm going wrong.
In my application I have Projects and Verifications. When viewing a particular Project, I need to be able to have a link to "Verify Project", which will send the user to a new Verification form. They will enter a variety of values, but I do not want them to have to select the Project that this Verification belongs to by hand -- I want to be able to pass the project_id directly alongside the values the user enters in the Verification form.
On my project view I have:
<%= link_to "Verify Project", new_verification_path(:project_id => #project.id ) %>
and then in the verifications controller:
def new
#verification = Verification.new(params[:verification])
#project = params[:project_id]
end
def create
#verification = Verification.new(params[:verification])
#verification.project = #project
end
but this yields this error:
Validation failed: Project does not exist, Project does not exist
How can I create my Verification with :project_id being grabbed from the previous page?
EDIT
From the Rails log:
(clicking Verify Project)
Started GET "/verifications/new?project_id=4" for 127.0.0.1 at
2013-09-10 04:02:56 +0200 Processing by VerificationsController#new as
HTML Parameters: {"project_id"=>"4"} Rendered
verifications/_form.html.erb (91.3ms) Rendered
verifications/new.html.erb within layouts/application (97.5ms)
Rendered layouts/_shim.html.erb (0.3ms) Account Load (0.2ms) SELECT
"accounts".* FROM "accounts" WHERE "accounts"."remember_token" =
'NuxEYIjeCYyFklN7EyHTDQ' LIMIT 1 Rendered layouts/_header.html.erb
(38.6ms) Rendered layouts/_footer.html.erb (0.3ms) Completed 200 OK
in 381ms (Views: 368.4ms | ActiveRecord: 2.7ms)
and then Create
Started POST "/verifications" for 127.0.0.1 at 2013-09-10 04:03:04
+0200 Processing by VerificationsController#create as HTML Parameters: {"utf8"=>"✓",
"authenticity_token"=>"sqUBXqA6y5oKCW1DFAi3sv8rQzm+tKjOYDdc/lvUS+c=",
"verification"=>{"verifier_name"=>"test", "checked_on(1i)"=>"2013",
"checked_on(2i)"=>"9", "checked_on(3i)"=>"10", "notes"=>"test"},
"commit"=>"Create Verification"} Account Load (0.2ms) SELECT
"accounts".* FROM "accounts" WHERE "accounts"."remember_token" =
'NuxEYIjeCYyFklN7EyHTDQ' LIMIT 1 (0.0ms) begin transaction
(0.1ms) rollback transaction Completed 422 Unprocessable Entity in
18ms
ActiveRecord::RecordInvalid (Validation failed: Project does not
exist, Project does not exist):
app/controllers/verifications_controller.rb:55:in `create'
EDIT 2
Here's the form for the Create action:
<%= form_for(#verification) do |f| %>
<% if #verification.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#verification.errors.count, "error") %> prohibited this verification from being saved:</h2>
<ul>
<% #verification.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="row">
<div class="span6 offset3">
<div class="field">
<%= f.label :verifier_name %><br />
<%= f.text_field :verifier_name %>
</div>
<div class="field">
<%= f.label :checked_on %><br />
<%= f.date_select :checked_on %>
</div>
<div class="field">
<%= f.label :notes %><br />
<%= f.text_area :notes %>
</div>
<div class="actions">
<%= f.submit %>
</div></div></div>
<% end %>
Your new controller action is a bit off. You're assigning an actual id to the #project instance variable, rather that the Project object that corresponds to that id. Subsequently, you're passing an invalid id from your new view to your create action.
Fix things by properly assigning the #project instance variable in your new action:
def new
#verification = Verification.new(params[:verification])
#project = Project.find(params[:project_id])
end
Then, you'll need to do a proper lookup of the a Project object in your create action:
def create
#verification = Verification.new(params[:verification])
#verification.project = Project.find(params[:project_id])
#verification.save
end
Finally, add the project_id as parameter in your form via the hidden_field form helper tag:
# in your `create` form
<%= f.hidden_field :project_id, :value => #project.id %>
You need to be sure that your project id is passed back to your create method. You can look up the project as in zeantsol's answer, or you can just pass the project ID. But you need to make sure that the form you create in your "new" view passes the project id back to your create method (perhaps in a hidden field)
See this post to see an example of using a hidden field in your view:
Rails hidden field undefined method 'merge' error
I have Realization model:
# encoding : utf-8
class Realization < ActiveRecord::Base
attr_accessible :city, :street, :title, :work, :photo, :date
has_attached_file :photo
end
Controller:
# encoding : utf-8
class RealizationsController < ApplicationController
before_filter :admin_required, :except => [:index,:show]
# GET /realization/new
def new
#realization = Realization.new
#realization.date = Time.now.__send__(:to_date).to_s
end
# POST /realization
def create
#realization = Realization.new(params[:realization])
if #realization.save
redirect_to #realization, notice: 'realization was successfully created.'
else
render action: "new"
end
end
(...) others
View of form:
<%= form_for #realization, :html => { :multipart => true } do |f| %>
<% if #realization.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#realization.errors.count, "error") %> prohibited this realization from being saved:</h2>
<ul>
<% #realization.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
(...)
<div class="field">
<%= f.file_field :photo %>
</div>
<div class="actions">
<%= f.submit "Submit" %>
</div>
<% end %>
And routes :
resources :realizations
And WEBrick server info is that:
Started POST "/realizacje" for 127.0.0.1 at 2013-04-12 12:26:35 +0200
Processing by RealizationsController#index as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"zK5jP4ChBBY+R21TjrZkp4xGvCHViTFJ+8Fw6Og28YY=", "realization"=>{"title"=>"wwwwww", "street"=>"", "city"=>"", "work"=>"", "date"=>"2013-04-12"}, "commit"=>"Submit"}
(1.0ms) SELECT COUNT(*) FROM "realizations"
Realization Load (2.0ms) SELECT "realizations".* FROM "realizations" ORDER BY created_at DESC LIMIT 7 OFFSET 0
User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Rendered realizations/index.html.erb within layouts/application (156.0ms)
Completed 200 OK in 340ms (Views: 333.0ms | ActiveRecord: 4.0ms)
While I use the form and push the submit it redirects/randers realizations/index without notice or errors even!
I have completely no idea why? Especialy that it worked before...
Maybe javascript added later on may be the reason?
Paperclip works well in update so it isn't it...
You might check your new action to see what you're passing in to the form_for.
You want to be passing in a brand new instance of your Realization model.
i.e. in the new action you should have a line that reads #realization = Realization.new
The reason I suggest this is because form_for calls a method (#new_record?) on the object you give it and will submit a post or put request depending on whether that method call returns true or false.