如何从一个提交更新两个_form?

如果他选择,current_user如何更新他的电子邮件而无需单独的提交按钮?

当前代码

           

总体思路

     # Or somehow remove form_for(current_user) altogether while still being able to update current_user.email within the form_for(@challenge)     

_form的形象

在此处输入图像描述

提供控制器代码,看看我们是否可以通过fields_for来完成这项工作

challenges_controller

 class ChallengesController  [], :committed => []) end end 

users_controller

 class UsersController < ApplicationController before_action :logged_in_user, only: [:index, :edit, :update, :destroy, :following, :followers] before_action :correct_user, only: [:edit, :update] def show @user = User.find(params[:id]) @past_challenges = @user.challenges.publish.order("deadline ASC").select{ |challenge| challenge.deadline < Date.current if challenge.deadline.present? } @past_challenges_by_years = @past_challenges.group_by { |t| t.deadline.beginning_of_year } @present_oneshot_challenges = @user.challenges.unaccomplished.publish.order("deadline ASC").select{ |challenge| challenge.deadline == Date.current if challenge.deadline.present? } @present_habit_challenges = @user.challenges.unaccomplished.publish.order("date_started DESC").select{ |challenge| challenge.date_started  Date.current if challenge.deadline.present? } @future_challenges_by_years = @future_challenges.group_by { |t| t.deadline.beginning_of_year } @inspirations = @user.inspirations.publish end def new @user = User.new end def create @user = User.new(user_params) if @user.save action = session.delete(:challenge_action) deadline = session.delete(:challenge_deadline) committed = session.delete(:challenge_committed) date_started = session.delete(:challenge_date_started) order = session.delete(:challenge_order) days_challenged = session.delete(:challenge_days_challenged) why = session.delete(:challenge_why) conceal = session.delete(:challenge_conceal) # Create if deadline.present? @user.challenges.create(action: action, deadline: deadline, why: why, conceal: conceal, date_started: date_started, committed: committed, days_challenged: days_challenged) end @user.send_welcome_email log_in @user redirect_to tutorial_url flash[:info] = 'Let the games begin! Add another challenge with + Challenge' else render 'new' end end def edit @user = User.find(params[:id]) end def update @user = User.find(params[:id]) if @user.update_attributes(user_params) redirect_to root_url flash[:success] = "Settings updated" else render 'edit' end end private def user_params if params[:conceal] = true params.require(:user).permit(:time_zone, :name, :email, :tag_list, :password, :conceal, inspirations_attributes: [:name, :tag_list, :conceal], activities_attributes: [:conceal, :action, :trackable_id, :trackable_type]) else params[:user][:conceal] = false params.require(:user).permit(:time_zone, :name, :image, :tag_list, :email, :password, inspirations_attributes: [:name, :tag_list], activities_attributes: [:action, :trackable_id, :trackable_type]) end end # Confirms a logged-in user. def logged_in_user unless logged_in? store_location flash[:danger] = "Please sign in first" redirect_to root_url end end # Confirms the correct user. def correct_user @user = User.find(params[:id]) redirect_to(root_url) unless current_user?(@user) end end 

在另一个form嵌入form不是有效的html 。 页面中可以有多个表单,但它们不能相互嵌入。

如果您希望以相同的forms包含不同模型的字段,则根据这些模型之间的关联,您可以使用form_forfields_for来呈现这些模型中的表单字段。 然后,当提交表单时,再次根据模型之间的关联,您可以保留数据。

您还可以使用javascript并提交/更新表单的部分内容。 例如:当text_field的内容发生更改时,您可以触发AJAX请求并保留数据。

有关详细信息,请参阅FormHelper#fields_for 。

更新:

根据您在评论中的回复,您有以下模型:

 class User < ActiveRecord::Base has_many :challenges end class Challenge < ActiveRecord::Base belongs_to :user end 

你有两种方法。

方法1:通过controller动作filter。 从controllerparams中截取用户的email并进行更新。 就像是:

 class ChallengesController < ApplicationController before_action :update_user_email, if: proc {|c| c.current_user.present? && c.params[:email].present? } private def update_user_email email = params[:email] current_user.update_attribute(:email, email) end end 

并按如下方式更新您的表单代码:

 <%= form_for(@challenge) do |challenge| %> # include fields for challenge <%= text_field_tag :email, current_user.email %> <%= challenge.submit %> <% end %> 

方法2:通过model回调。 使用attr_accessor和模型中的callbacks的组合。

 class Challenge < ActiveRecord::Base belongs_to :user attr_accessor :user_email before_save :update_user_email, if: :user_email_present? protected def user_email self.user.email if self.user.present? end def user_email_present? self.user_email.present? end def update_user_email # based on your logic in controller, looks like the # `current_user` and the `user` of the `challenge` # are one and the same. So you could directly update # `email` on the `user` object. self.user.update_attribute(:email, self.user_email) end end 

并按如下方式更新您的表单代码:

 <%= form_for(@challenge) do |challenge| %> # include fields for challenge <%= challenge.text_field :user_email, current_user.email %> <%= challenge.submit %> <% end %>