如何从一个提交更新两个_form? [英] How to update two _form from one submit?
问题描述
如果current_user没有单独的提交按钮,current_user如何更新他的电子邮件?
当前代码 p>
<%= form_for(@challenge)do | challenge | %GT;
<%= challenge.action%>
<%= challenge.send_email%>
<%end%>
<%= form_for(current_user)do | user | %GT;
<%= user.email%>
<%= user.submit%>
<%end%>
<%= form_for(@challenge)do | challenge | %GT;
<%= challenge.submit%>
<%end%>
整体构思
<%= form_for(@challenge)do | challenge | %GT;
<%= challenge.action%>
<%= challenge.send_email%>
<%= form_for(current_user)do | user | %GT; #或者以某种方式完全删除form_for(current_user),同时仍然能够更新form_for(@challenge)中的current_user.email
<%= user.email%>
<%end%>
<%= challenge.submit%>
<%end%>
_form图片
提供控制器代码来查看我们是否可以通过fields_for来完成这项工作。
$ b
challenges_controller
class ChallengesController< ApplicationController
before_action:set_challenge,仅:[:show::edit,:update,:destroy,::challenge,:mark_accomplished,:mark_completed,:create_freebie,:like]
respond_to:html,:json
def show
@challenge_to_deadline = current_user.challenges.group_by {| i | i.deadline} if current_user
@notable = @challenge
@notes = @ notable.notes
@note = Note.new
@commentable = @challenge
@评论= @ commentable.comments
@comment = Comment.new
@correct_user = current_user.challenges.find_by(id:params [:id])
结束
def new
@challenge = Challenge.new
respond_modal_with @challenge,位置:root_path
结束
$ b $ def编辑
结束
def创建
@challenge = Challenge.new(challenge_params)
if params [:step] =='2'
if current_user == nil
#如果没有用户,将生存期值存储到会话中。
session [:challenge_action] = challenge_params [:action]
session [:challenge_committed] = challenge_params [:committed]
session [:challenge_deadline] = [params [challenge] [deadline (3i)],params [challenge] [deadline(2i)],params [challenge] [deadline(1i)]]。join('/')
session [: challenge_date_started] = [params [challenge] [date_started(3i)],params [challenge] [date_started(2i)],params [challenge] [date_started(1i)]]。 join('/')
session [:challenge_order] = challenge_params [:order]
session [:challenge_days_challenged] = challenge_params [:days_challenged]
session [:challenge_why] = challenge_params [:why ]
session [:challenge_conceal] = challenge_params [:conceal]
redirect_to signup_path
else
@challenge = current_user.challenges.build(challenge_params)
if @challenge。隐藏== true
@ challenge.save
re direct_to root_path
if @ challenge.date_started.present?
flash [:info] ='习惯秘密保存!点击罢工1完成一天。'
else
flash [:info] ='目标挑战秘密保存! '
end
elsif
@ challenge.save
track_activity @challenge
redirect_to root_path
if @ challenge.date_started.present?
flash [:info] ='习惯保存的挑战!点击Strike 1完成一天。'
else
flash [:info] ='目标挑战保存! '
end
else
respond_modal_with @challenge
end
end
end
end
def update
@ challenge.update(challenge_params)
flash [:info] ='挑战更新'
respond_modal_with @challenge,位置:root_path
结束
私人
def set_challenge
@challenge = Challenge.find(params [:id])
结束
def challenge_params
params.require(:challenge).permit(
:action,
:为什么,
:like,
:截止日期,
:已完成,
: tag_list,
:隐藏,
:归档,
:触发器,
:错过日期,
:target,
:奖励,
:顺序,
:date_started,
:date_ended,
:days_challenged,
:completed_at,
:免费赠品,
:freebie_date,
:sen d_email => [],
:committed => [])
结束
结束
users_controller
class UsersController< ApplicationController
before_action:只有logged_in_user:[:index::edit,:update,:destroy,:following,:followers]
before_action:只有correct_user:[:edit,:update]
def show
@user = User.find(params [:id])
@past_challenges = @ user.challenges.publish.order(deadline ASC)。select {| challenge | challenge.deadline< Date.current如果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.tomorrow如果challenge.date_started.present? }
@future_challenges = @ user.challenges.unaccomplished.publish.order(deadline ASC)。select {| challenge | challenge.deadline> Date.current如果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
$ b $ def创建
@user = User.new(user_params)
if @ user.save
action = session.delete(:challenge_action)
截止日期= 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)
#如果deadline.present创建
?
@ user.challenges.create(操作:操作,截止日期:截止日期,原因:为什么,隐藏:隐藏,date_started:date_started,提交:提交,days_challenged:days_challenged)
结束
@user .send_welcome_email
log_in @user
redirect_to tutorial_url
flash [:info] ='让游戏开始! +挑战'添加另一个挑战'
else
渲染'新'
结束
结束
def编辑
@user = User.find (params [:id])
end
$ b def update
@user = User.find(params [:id])
if user.update_attributes(user_params )
redirect_to root_url
flash [:success] =设置更新
else
渲染'编辑'
结束
结束
private
$ b 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])
结束
结束
#确认登录用户。
def logged_in_user
除非logged_in?
store_location
flash [:danger] =请先登录
redirect_to root_url
结束
结束
#确认用户正确。
def correct_user $ b $ @user = User.find(params [:id])
redirect_to(root_url)除非current_user?(@user)
结束
结束
嵌入表格
在另一个窗体
内无效 html
。在页面中可以有多种形式,但是它们不能相互嵌套。
如果您希望具有相同形式的不同模型的字段,根据这些模型之间的关联,您可以在 form_for
中使用 fields_for
来渲染这些模型中的表单字段。然后当表单被提交时,再次取决于模型之间的关联,您可以保存数据。
您也可以使用 javascript
并提交/更新表单的一部分。例如:当 text_field
的内容发生变化时,您可以触发 AJAX
请求并保存数据。 / p>
请参阅 FormHelper#fields_for 获取更多信息。
更新:
class User< p>根据您在评论中的回复,您有以下模型: ActiveRecord :: Base
has_many:挑战
结束
挑战< ActiveRecord :: Base
belongs_to:user
end
您有两种方法。方法1:通过控制器
动作过滤器。从控制器
中的 params
拦截用户的电子邮件
和更新它。例如:
class ChallengesController< ApplicationController
before_action:update_user_email,如果:proc {| c | c.current_user.present? &安培;&安培; c.params [:邮箱] .present? }
private
def update_user_email
email = params [:email]
current_user.update_attribute(:email,email)
end
end
更新您的表单代码如下:
<%= form_for(@challenge)do | challenge | %GT;
#包含挑战字段
<%= text_field_tag:email,current_user.email%>
<%= challenge.submit%>
<%end%>
方法2:通过模型
回调。在模型中使用 attr_accessor
和回调
的组合。
class挑战< ActiveRecord :: Base
belongs_to:user
attr_accessor:user_email
before_save:update_user_email,如果:: user_email_present?
保护
def user_email
self.user.email if self.user.present?
结束
def user_email_present?
self.user_email.present?
end
$ b $ def update_user_email
#根据您的控制器逻辑,看起来像
#`current_user`和``challenge`的`user`
#是一个一样的。所以你可以直接在`user`对象上更新
#`email`。
self.user.update_attribute(:email,self.user_email)
结束
结束
然后更新您的表单代码,如下所示:
<%= form_for(@challenge)do | challenge | %GT;
#包含挑战字段
<%= challenge.text_field:user_email,current_user.email%>
<%= challenge.submit%>
<%end%>
How can the current_user update his email, if he chooses, without having to have a separate submit button?
current code
<%= form_for(@challenge) do |challenge| %>
<%= challenge.action %>
<%= challenge.send_email %>
<% end %>
<%= form_for(current_user) do |user| %>
<%= user.email %>
<%= user.submit %>
<% end %>
<%= form_for(@challenge) do |challenge| %>
<%= challenge.submit %>
<% end %>
overall idea
<%= form_for(@challenge) do |challenge| %>
<%= challenge.action %>
<%= challenge.send_email %>
<%= form_for(current_user) do |user| %> # Or somehow remove form_for(current_user) altogether while still being able to update current_user.email within the form_for(@challenge)
<%= user.email %>
<% end %>
<%= challenge.submit %>
<% end %>
image of _form
Offering controllers code to see if we can make this work via fields_for
challenges_controller
class ChallengesController < ApplicationController
before_action :set_challenge, only: [:show, :edit, :update, :destroy, :challenging, :mark_accomplished, :mark_completed, :create_freebie, :like]
respond_to :html, :json
def show
@challenge_to_deadline = current_user.challenges.group_by {|i| i.deadline} if current_user
@notable = @challenge
@notes = @notable.notes
@note = Note.new
@commentable = @challenge
@comments = @commentable.comments
@comment = Comment.new
@correct_user = current_user.challenges.find_by(id: params[:id])
end
def new
@challenge = Challenge.new
respond_modal_with @challenge, location: root_path
end
def edit
end
def create
@challenge = Challenge.new(challenge_params)
if params[:step] == '2'
if current_user == nil
# If there is no user, store the lifetime values to the session.
session[:challenge_action] = challenge_params[:action]
session[:challenge_committed] = challenge_params[:committed]
session[:challenge_deadline] = [params["challenge"]["deadline(3i)"], params["challenge"]["deadline(2i)"], params["challenge"]["deadline(1i)"]].join('/')
session[:challenge_date_started] = [params["challenge"]["date_started(3i)"], params["challenge"]["date_started(2i)"], params["challenge"]["date_started(1i)"]].join('/')
session[:challenge_order] = challenge_params[:order]
session[:challenge_days_challenged] = challenge_params[:days_challenged]
session[:challenge_why] = challenge_params[:why]
session[:challenge_conceal] = challenge_params[:conceal]
redirect_to signup_path
else
@challenge = current_user.challenges.build(challenge_params)
if @challenge.conceal == true
@challenge.save
redirect_to root_path
if @challenge.date_started.present?
flash[:info] = 'habit Challenge secretly saved! Click "Strike 1" upon incompleting a day.'
else
flash[:info] = 'goal Challenge secretly saved! Click checkmark upon completing it.'
end
elsif
@challenge.save
track_activity @challenge
redirect_to root_path
if @challenge.date_started.present?
flash[:info] = 'habit Challenge saved! Click "Strike 1" upon incompleting a day.'
else
flash[:info] = 'goal Challenge saved! Click checkmark upon completing it.'
end
else
respond_modal_with @challenge
end
end
end
end
def update
@challenge.update(challenge_params)
flash[:info] = 'Challenge updated'
respond_modal_with @challenge, location: root_path
end
private
def set_challenge
@challenge = Challenge.find(params[:id])
end
def challenge_params
params.require(:challenge).permit(
:action,
:why,
:like,
:deadline,
:accomplished,
:tag_list,
:conceal,
:archive,
:trigger,
:missed_days,
:target,
:reward,
:order,
:date_started,
:date_ended,
:days_challenged,
:completed_at,
:freebie,
:freebie_date,
:send_email => [],
: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.tomorrow if challenge.date_started.present? }
@future_challenges = @user.challenges.unaccomplished.publish.order("deadline ASC").select{ |challenge| challenge.deadline > 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
Embedding form
within another form
is not valid html
. There can be multiple forms with in a page, but they cannot be embedded within each other.
If you want to have fields for different models with in the same form, depending upon the association between those models, you could make use of fields_for
within the form_for
to render the form fields from those models. And then when the form is submitted, again depending upon the associations between the models, you could persist the data.
You could also make use of javascript
and submit/update parts of the form. For example: when the contents of the text_field
have changed, you could trigger an AJAX
request and persist the data.
Refer to FormHelper#fields_for for more info.
Update:
Based on your response in the comments, as you have the following models:
class User < ActiveRecord::Base
has_many :challenges
end
class Challenge < ActiveRecord::Base
belongs_to :user
end
You have two approaches.
Approach 1: Through controller
action filters. Intercept the user's email
from the params
in the controller
and update it. Something like:
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
And update your form code as follows:
<%= form_for(@challenge) do |challenge| %>
# include fields for challenge
<%= text_field_tag :email, current_user.email %>
<%= challenge.submit %>
<% end %>
Approach 2: Through model
callbacks. Using a combination of attr_accessor
and the callbacks
in the model.
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
And update your form code as follows:
<%= form_for(@challenge) do |challenge| %>
# include fields for challenge
<%= challenge.text_field :user_email, current_user.email %>
<%= challenge.submit %>
<% end %>
这篇关于如何从一个提交更新两个_form?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!