I'm creating a profile that is associated with a member id based on Devise authentication.
When creating the profile, the values aren't inserted into the database.
Routes file.
resources :troopers do
resource :trooper_profile
end
Trooper model
has_one :trooper_profile
Trooper Profile model
belongs_to :trooper
Trooper Controller #create action
def create
#trooper = current_trooper
#profile = #trooper.build_trooper_profile(params[:profile])
respond_to do |format|
if #profile.save
format.html { redirect_to(trooper_trooper_profile_path, :notice => 'Profile was successfully created.') }
else
format.html { render :action => "new" }
end
end
end
Profile Form
<%= form_for #profile, :url => trooper_trooper_profile_path(#trooper) do |f| %>
<%= f.label :first_name %><br />
<%= f.text_field :first_name %><br /><br />
<%= f.label :last_name %><br />
<%= f.text_field :last_name %><br /><br />
<p><%= submit_tag "Create Profile" %></p>
<% end %>
Server output
Started POST "/troopers/1/trooper_profile" for 127.0.0.1 at 2011-05-20 13:04:01 +1000
Processing by TrooperProfilesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"LhT6b4xu5bIJ5kwhS74L7dpaGbuR5BTdirh9AziD+Ew=", "trooper_profile"=>{"first_name"=>"Robert", "last_name"=>"", "commit"=>"Create Profile", "trooper_id"=>"1"}
Trooper Load (0.5ms) SELECT "troopers".* FROM "troopers" WHERE ("troopers"."id" = 1) LIMIT 1
TrooperProfile Load (0.3ms) SELECT "trooper_profiles".* FROM "trooper_profiles" WHERE ("trooper_profiles".trooper_id = 1) LIMIT 1
Rendered trooper_profiles/_form.html.erb (11.7ms)
Rendered shared/_head.html.erb (1.6ms)
Rendered shared/_menutop.html.erb (1.2ms)
Rendered trooper_profiles/new.html.erb within layouts/application (18.5ms)
Completed 200 OK in 109ms (Views: 22.5ms | ActiveRecord: 0.8ms)
I've got this same setup in another application and can't see why this isn't working.
Change the following...
#profile = #trooper.build_trooper_profile(params[:trooper_profile])
It appears the parameters being passed are :trooper_profile
trooper_profile"=>{"first_name"=>"Robert", "last_name"=>"", "commit"=>"Create Profile", "trooper_id"=>"1"}
However, you're referencing :profile
If it's rendering the new view, then the profile isn't saving - perhaps it's a validation error? Does TrooperProfile require a last name (blank in your example)?
Related
I have an app running rails 6.1.3.2. I'm starting to migrate to use hotwire instead of ujs. My app uses an admin namespace to allow a user to make edits, create items via this. Example route below -
resources :event_attachments
namespace :admin do
resources :event_attachments
end
When making an update via the admin view to an event_attachment, the turbo_stream is not processing the partial in the admin view, instead it's looking in EventAttachmentsController. I'm not sure why it's doing this - any suggestions would be appreciated.
Admin:EventAttachmentsController -
def update
if #event_attachment.update(event_attachment_params)
respond_to do |format|
format.turbo_stream do
render turbo_stream: [
turbo_stream.update("flash", partial: "shared/flash", locals: { notice: "Event image updated" }),
turbo_stream.replace(:event_attachments, partial: 'admin/pages/event_attachment', locals: { event_attachment: #event_attachment })
]
end
format.html do
redirect_to edit_admin_event_attachment_path(#event_attachment), notice: 'Event image updated'
end
end
else
render :edit, status: :unprocessable_entity
end
end
Here's a sample of my form in admin/event_attachments -
<%= form_for([:admin, event_attachment], :id => dom_id(event_attachment)) do |f| %>
<%= f.text_field :title, :placeholder => "Event image name *" %>
<% end %>
Rails Server Log (as a test, I created a partial in the main event_attachments view) -
Started PATCH "/event_attachments/25" for ::1 at 2022-01-03 22:18:53 -0500
Processing by EventAttachmentsController#update as TURBO_STREAM
Parameters: {"utf8"=>"✓", "authenticity_token"=>"[FILTERED]", "event_attachment"=>{"title"=>"Test Name", "summary"=>"caption"}, "commit"=>"Save Changes", "id"=>"25"}
EventAttachment Load (1.1ms) SELECT `event_attachments`.* FROM `event_attachments` WHERE `event_attachments`.`id` = 25 LIMIT 1
↳ app/controllers/event_attachments_controller.rb:51:in `set_event_attachment'
Rendered event_attachments/_event_attachment.html.erb (Duration: 0.1ms | Allocations: 22)
[ActionCable] Broadcasting to event_attachments: "<turbo-stream action=\"update\" target=\"event_attachment_25\"><template><li id=\"event_attachment_25\">\n hello\n</li>\n</template></turbo-stream>"
Redirected to http://localhost:3000/event_attachments/25
Completed 302 Found in 4ms (ActiveRecord: 1.1ms | Allocations: 1640)
It looks like the problem here is in the url that your form is sending the request to. If you look in the logs you will see it says processing by EventAttachmentsController#update this is because in your form the URL is wrong. My thoughts is you should change from using form_for and the [] to use form_with
<%= form_with(url: admin_event_attachments_path, :id => dom_id(event_attachment)) do |f| %>
<%= f.text_field :title, :placeholder => "Event image name *" %>
<% end %>
I have a form_with that works in my server but not in my brother:
My form in my view :
<%= form_with url: sessions_path, method: "post" do |f|%>
<h3 class="text-center text-info">Se Connecter</h3>
<div class="form-group">
<%= label_tag "email", "Adresse mail:", class: "text-info" %><br>
<%= f.email_field "email", class: "form-control" %>
</div>
<div class="form-group">
<%= label_tag "password", "Mot De Passe", class: "text-info" %><br>
<%= f.password_field "password", class: "form-control" %>
</div>
<div class="form-group" style="padding: 20px;">
<%= f.submit "Se connecter", class: "btn btn-info btn-md" %>
</div>
<% end %>
My controller :
def create
user = User.find_by(email: params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to gossips_path, :notice => "Bienvenue <%= User.find_by(id: session[:user_id]).first_name %>"
else
flash.now[:danger] = 'Email ou Mot De Passe invalide'
render 'new'
end
end
My server :
Started POST "/sessions" for ::1 at 2020-10-04 13:10:25 +0200
Processing by SessionsController#create as JS
Parameters: {...}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."email" = $1 LIMIT $2 [["email", "..."], ["LIMIT", 1]]
↳ app/controllers/sessions_controller.rb:8
#<User:0x00007f667d7f36f0>
Redirected to http://localhost:3000/gossips
Completed 302 Found in 246ms (ActiveRecord: 0.2ms)
Started GET "/gossips" for ::1 at 2020-10-04 13:10:26 +0200
Processing by GossipsController#index as JS
Rendering gossips/index.html.erb within layouts/application
Gossip Load (0.4ms) SELECT "gossips".* FROM "gossips"
↳...
Rendered gossips/index.html.erb within layouts/application (75.5ms)
Completed 200 OK in 102ms (Views: 85.6ms | ActiveRecord: 12.8ms)
But my browser stay in the same page. I don't know why.
Can you help me?
<%= form_with url: sessions_path, method: "post", local: true do |f|%>
# ...
<% end %>
form_with unlike form_for defaults to remote: true. That means that the form will by default send an AJAX request and thus the redirect does nothing in the browser. You can see that its an AJAX request by:
Processing by SessionsController#create as JS
So I've been at this a while and have tried a bunch of different methods. Essentially I have an over-arching property model and an associated deed model. From the properties#show view I have it displaying all associated deeds. I have a button in my property view that displays a modal (using AJAX) to create a deed associated to said model. All the steps work (even 'edit' and 'update' using AJAX from the properties view) except when trying to save the new deed I get an error message:
This form contains 1 error. Property must exist
I've tried passing the #properties.id through in different ways and I just can't seem to get it. I'll list all the relevant info I have and if more is needed just let me know.
Property Model
class Property < ApplicationRecord
has_many :deeds, dependent: :destroy
accepts_nested_attributes_for :deeds
end
Deeds Model
class Deed < ApplicationRecord
belongs_to :property
accepts_nested_attributes_for :property
end
Deeds Controller (Included edit and update actions)
def new
#deeds = Deed.new
#deeds.build_property
respond_to do |format|
format.html { render 'new'}
format.js
end
end
def create
#properties = Property.find(params[:deed][:property_id])
#deeds = #properties.deeds.new(deed_params)
if #deeds.save
flash[:success] = "Deed created successfully!"
respond_to do |format|
format.html { redirect_to deeds_path }
format.js
end
else
render 'new'
end
end
def edit
#deeds = Deed.find(params[:id])
respond_to do |format|
format.html { #deeds.save }
format.js
end
end
def update
#deeds = Deed.find(params[:id])
#properties = Property.find(#deeds.property.id)
#deeds.update_attributes(deed_params)
respond_to do |format|
format.html { redirect_to deeds_path }
format.js
end
end
private
def deed_params
params.require(:deed).permit(:property_id, :deed_number, :deed_context, :consideration, :recorded_date, :grantor, :grantee, :trustee)
end
new deeds link from properties#show view
<%= link_to fa_icon("plus", text: "Add Deed"), new_property_deed_path(#properties.id), remote: true, class: "btn btn-primary btn-large btn-ouline pull-right", locals: { property_id: #properties } %>
new.js.erb
$('#deeds-modal').modal("show");
$('#deeds-modal').html('<%= j render partial: "deeds/deeds_modal", locals: { property_id: #properties } %>');
_deeds_modal.html.erb partial Form
<div class="modal-body">
<%= bootstrap_form_for(#deeds, layout: :horizontal, remote: true) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.hidden_field :property_id, value: property_id %>
<%= f.text_field :deed_number, class: 'form-control' %>
<%= f.text_field :deed_context, class: 'form-control' %>
<%= f.text_field :consideration, class: 'form-control' %>
<%= f.text_field :recorded_date, class: 'form-control' %>
<%= f.text_field :grantor, class: 'form-control' %>
<%= f.text_field :grantee, class: 'form-control' %>
<%= f.text_field :trustee, class: 'form-control' %>
<%= f.form_group do %>
<%= f.submit "Save", class: "btn btn-primary" %>
<% end %>
<% end %>
</div>
server response upon deeds_modal form POST
Started GET "/properties/99/deeds/new" for 127.0.0.1 at 2017-05-30
23:24:48 -0400
Processing by DeedsController#new as JS
Parameters: {"property_id"=>"99"}
Rendering deeds/new.js.erb
Rendered shared/_error_messages.html.erb (0.4ms)
Rendered deeds/_deeds_modal.html.erb (5.6ms)
Rendered deeds/new.js.erb (7.3ms)
Completed 200 OK in 14ms (Views: 10.6ms | ActiveRecord: 0.0ms)
Started POST "/deeds" for 127.0.0.1 at 2017-05-30 23:24:55 -0400
Processing by DeedsController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"eaj9K...==", "deed"=>{"property_id"=>"", "deed_number"=>"69696969", "deed_context"=>"Bagel slaps", "consideration"=>"Considered", "recorded_date"=>"2017-05-31", "grantor"=>"", "grantee"=>"NipLips", "trustee"=>""}, "commit"=>"Save"}
(0.1ms) BEGIN
(0.1ms) ROLLBACK
Rendering deeds/new.js.erb
Rendered shared/_error_messages.html.erb (0.7ms)
Rendered deeds/_deeds_modal.html.erb (12.1ms)
Rendered deeds/new.js.erb (20.4ms)
Completed 200 OK in 32ms (Views: 30.6ms | ActiveRecord: 0.2ms)
So as you can see I've tried to pass through a local variable from the new link -> new.js.erb -> deeds modal form but I can't seem to pull the property_id into the new deeds object.
Is this even the correct approach for what I'm trying to do or am I just missing something? Hope this wasn't too long of a read and that I provided enough info... lol.
*Upon writing this post I clicked through some of the 'similar questions' on SO, which is where I got the #properties = Property.find(params[:deed][:property_id]) line from but I still get ActiveRecord::RecordNotFound (Couldn't find Property with 'id'=): upon submission. Also, thank you to anyone who takes the time to read this.
rails routes Update (only included relevant routes for brevity)
deeds GET /deeds(.:format) deeds#index
POST /deeds(.:format) deeds#create
new_deed GET /deeds/new(.:format) deeds#new
edit_deed GET /deeds/:id/edit(.:format) deeds#edit
deed GET /deeds/:id(.:format) deeds#show
PATCH /deeds/:id(.:format) deeds#update
PUT /deeds/:id(.:format) deeds#update
DELETE /deeds/:id(.:format) deeds#destroy
...
property_deeds GET /properties/:property_id/deeds(.:format) deeds#index
POST /properties/:property_id/deeds(.:format) deeds#create
new_property_deed GET /properties/:property_id/deeds/new(.:format) deeds#new
edit_property_deed GET /properties/:property_id/deeds/:id/edit(.:format) deeds#edit
property_deed GET /properties/:property_id/deeds/:id(.:format) deeds#show
PATCH /properties/:property_id/deeds/:id(.:format) deeds#update
PUT /properties/:property_id/deeds/:id(.:format) deeds#update
DELETE /properties/:property_id/deeds/:id(.:format) deeds#destroy
This should be you new action
def new
#deeds = Deed.new
#deeds.build_property
#properties = Property.find_by_id(params[:property_id]) # add this line
respond_to do |format|
format.html { render 'new'}
format.js
end
end
Update:
If you are not using the associated property anywhere else, you don't need to pass the locals and I don't suggest hidden_field as it can be easily modified, alternately you can do..
def new
#deeds = Property.find_by_id(params[:property_id]).deeds.new # add this line
#deeds.build_property
respond_to do |format|
format.html { render 'new'}
format.js
end
end
As the error says Property must exist, so, your intention is to print the property_id for a new record, but for some reason that's not happening.
As that value goes from your form_for directly to create a new "deed", then in must be setted on it, you do it, but you don't check if it's printing something or not, and it get's you a nil value that's not allowed because of the relationship between Deeds and Properties.
When you send the form, you can see the value is empty:
"deed"=>{"property_id"=>""}
How do you define which property_id must a new record have? You can create a variable within your new method and set an object to print within your form_for, it'll give you a value to proceed with a new record.
When you make a request to the new method you pass through the params the value for property_id:
Processing by DeedsController#new as JS
Parameters: {"property_id"=>"99"}
So I suppose you could use it instead setting a local variable which hasn't been initialized, maybe you can try with:
<%= f.hidden_field :property_id, value: params[:property_id] %>
I am trying to create a basic form where the user can change their password but needs to enter their old password in order to do it. I am having trouble verifying the user's old password. Everytime I enter an old password it says password doesn't match when I know that it does. If a replace the actual password in the authenticate field it works. How can I bring in what was entered in the form to verify the old password that was entered?
Form:
<%= form_for(#user, :url => change_password_action_path(current_user.id), html: { "role" => "form" }) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="form-group">
<%= f.label :old_password, "Old Password:", :class => "control-label" %>
<%= f.password_field :old_password, :class => "form-control" %>
</div>
<div class="form-group">
<%= f.label :password, "New Password:", :class => "control-label" %>
<%= f.password_field :password, :class => "form-control" %>
</div>
<div class="form-group">
<%= f.label :password_confirmation, "Password Confirmation:", :class => "control-label" %>
<%= f.password_field :password_confirmation, :class => "form-control" %>
</div>
<%= f.submit "Update Password", class: "btn btn-large btn-primary" %>
Controller
def change_password
#user = User.find(current_user.id)
end
def change_password_action
user = current_user.id
if User.find(user).authenticate(params[:old_password]) == false
flash[:danger] = "Password Doesnt Match: "
else
flash[:success] = "Password Match"
# Validate the new and confirm password.
end
redirect_to action: :change_password
end
Routes
get '/change_password' => 'main#change_password'
patch '/change_password_action' => 'main#change_password_action'
Rails Server Logs
Started PATCH "/change_password_action.1" for 127.0.0.1 at 2014-01-15 09:04:38 -0600
Processing by MainController#change_password_action as
Parameters: {"utf8"=>"✓", "authenticity_token"=>"yYdUx37Q7alr3SccuMVjPwCJoMgMPOaiKTesSsILlP4=", "user"=>{"old_password"=>"[FILTERED]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Update Password"}
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'fc1baf63bac072bfefd5ed27664ece5427ad9e64' LIMIT 1
{"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"yYdUx37Q7alr3SccuMVjPwCJoMgMPOaiKTesSsILlP4=", "user"=>{"old_password"=>"test123", "password"=>"", "password_confirmation"=>""}, "commit"=>"Update Password", "controller"=>"main", "action"=>"change_password_action", "format"=>"1"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Redirected to http://localhost:3000/change_password
Completed 302 Found in 115ms (ActiveRecord: 0.7ms)
Started GET "/change_password" for 127.0.0.1 at 2014-01-15 09:04:39 -0600
Processing by MainController#change_password as HTML
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'fc1baf63bac072bfefd5ed27664ece5427ad9e64' LIMIT 1
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Rendered shared/_error_messages.html.erb (0.1ms)
Rendered main/change_password.html.erb within layouts/application (2.6ms)
Rendered layouts/_header.html.erb (0.5ms)
Rendered layouts/_footer.html.erb (0.0ms)
Completed 200 OK in 19ms (Views: 16.2ms | ActiveRecord: 0.4ms)
It looks like you're passing the wrong parameter into your authenticate method.
Try using params[:user][:old_password] instead of params[:old_password].
The param value you want will be under the :user key, because your form_for is using a user object.
You can also see this in your server logs where the user param in your params hash is:
"user"=>{"old_password"=>"[FILTERED]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}
This is my login form
<%= form_for Customer.new, url: {action: :login} do |f| %>
<%= f.text_field :username,placeholder: 'Username or Email' %>
<%= f.password_field :password,placeholder: 'Password' %>
<%= f.submit 'Login' %>
<% end %>
This is my controller
def login
username = params[:username]
password = params[:password]
unless username.blank? && password.blank?
#My code doesn't entering to this block
end
end
If i submit form it is just submitted it doesn't perform any action
Edit 1
This is what my console return when form submitted
Started POST "/auth/login" for 127.0.0.1 at 2013-09-08 08:23:05 +0530
Processing by AuthController#login as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"9f7TKlIspKQwX7jMSzI7XGrabgJKvnzj8Ip0OLTDtW4=", "customer"=>{"username"=>"xxx", "password"=>"[FILTERED]"}, "commit"=>"Login"}
Rendered auth/login.html.erb within layouts/application (3.5ms)
Rendered layouts/_header.html.erb (0.4ms)
Completed 200 OK in 21ms (Views: 19.3ms | ActiveRecord: 0.0ms)
If you check your params hash you'll see that those keys don't exist. Instead, you'll see that params[:custpmer] does and that it contains those fields. This is just how rails builds the params in a form_for style. So try this instead:
username = params[:customer][:username]
password = params[:customer][:password]