Form doesn't save: doesn't seem to pass on parent_id?

时间:2015-04-30 10:24:42

标签: ruby-on-rails ruby ruby-on-rails-4

I have a form that includes two models, one of which is nested in another. When on the development server I submit the form, the submission generates the flash error message:

The form contains 1 error: 
* Members organization can't be blank

Each Member belongs to 1 Organization. Might the error have to do with that the organization isn't saved yet when it's trying to save the Member (for a new organization, it's supposed to simulateneously save the organization and member)? Should I add code that sets organization_id for the member (but I would expect @organization.members.build to take care of that)? What am I doing wrong here?

The server log:

Processing by OrganizationsController#create as HTML
  Parameters: {"utf8"=>"✓", "organization"=>{"org_name"=>"sadfsdaf", "phone"=>"sdfds", "members_attributes"=>{"0"=>{"username"=>"fsfdsfsad", "email"=>"sfdsdf@sfsdf.com", "fullname"=>"sdfds", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}}, "admin"=>"true", "commit"=>"Sign up"}
   (0.5ms)  begin transaction
  Member Exists (0.4ms)  SELECT  1 AS one FROM "members" WHERE LOWER("members"."email") = LOWER('sfdsdf@sfsdf.com') LIMIT 1
  Member Exists (0.2ms)  SELECT  1 AS one FROM "members" WHERE LOWER("members"."username") = LOWER('fsfdsfsad') LIMIT 1
  Organization Exists (0.3ms)  SELECT  1 AS one FROM "organizations" WHERE LOWER("organizations"."org_name") = LOWER('sadfsdaf') LIMIT 1
  Organization Exists (0.2ms)  SELECT  1 AS one FROM "organizations" WHERE LOWER("organizations"."phone") = LOWER('sdfds') LIMIT 1
   (0.2ms)  rollback transaction
  Rendered shared/_error_messages.html.erb (1.9ms)

Organization model:

has_many :members, dependent: :destroy
accepts_nested_attributes_for :members, :reject_if => :all_blank, :allow_destroy => true

Member model:

belongs_to :organization

validates :organization_id, presence: true  # There are other validations as well, but I don't think they matter for this question.

def send_activation_email
  MemberMailer.account_activation(self).deliver_now
end

Organization controller:

def new
  @organization = Organization.new
  @member = @organization.members.build
end

def create
  @organization = Organization.new(organizationnew_params)
  if @organization.save
    @member.send_activation_email  # Method in Member model file.
    flash[:success] = "Please check your email to activate your account."
    redirect_to root_url
  else                          
    render 'new'
  end
end

private
def organizationnew_params
  params.require(:organization).permit(:org_name,
                                      :phone,
                   member_attributes: [:email,
                                      :username,
                                      :admin,
                                      :password,
                                      :password_confirmation
                                      ])
end

New view:

<%= form_for(@organization) do |f| %>
  <%= f.text_field :org_name, %>
  <%= f.text_field :phone %>

  <%= f.fields_for :members do |p| %>
    <%= p.text_field :username %>
    <%= p.email_field :email %>
    <%= p.password_field :password %>
    <%= p.password_field :password_confirmation %>
    <%= hidden_field_tag :admin, true %> 
  <% end %>

  <%= f.submit "Sign up", class: "formbutton btn btn-default" %>
<% end %>

2 个答案:

答案 0 :(得分:1)

在允许的参数上,尝试将member_attributes更改为members_attributes。同样在创建操作上您指的是@member,但尚未定义。

要进一步调试,请使用以下命令替换您的创建操作:

def create
  return render text: organizationnew_params
end

这样,当您发送表格时,您将获得所有允许的参数,并检查它是否符合您的预期。

发送电子邮件替换

@member.send_activation_email

使用

@organization.members.each do |single_member|
  single_member.send_activation_email
end

第三次编辑

请使用此

def create
  @organization = Organization.new(organizationnew_params)
  if @organization.save
    @organization.members.each do |single_member|
      single_member.send_activation_email
    end
    flash[:success] = "Please check your email to activate your account."
    redirect_to root_url
  else                          
    render 'new'
  end
end

private

def organizationnew_params
  params.require(:organization).permit(:org_name,
                                      :phone,
                   members_attributes: [:id,:email,
                                      :username,
                                      :admin,
                                      :password,
                                      :password_confirmation
                                      ])
end

第四次编辑

验证:

使用membersoraganization)创建OraganizationsController时,您无需验证organization_id,因为它将在{organization的同一时间创建1}}。很遗憾,在向organization_id添加新的member时,您需要验证organization。所以我们可以做的是为验证添加一个条件:

#member.rb
attr_accessor :require_organization_id
belongs_to :organization

validates :organization_id, presence: true, if: :require_organization_id

如何使用它:

member = Member.new(name: "Some Name")
member.valid? #true
member.require_organization_id = true
member.valid? #false
member.organization = Organization.first
member.valid? #true

答案 1 :(得分:0)

如果在成员模型中设置验证,即

validates :organization_id, presence: true

然后它会在member_id的成员参数中查找并不存在于memeber的参数中

"members_attributes"=>{"0"=>{"email"=>"sfsa@sfsd.com", "username"=>"fsfdsfsad", "fullname"=>"sdfds", "password"=>"foobar", "password_confirmation"=>"foobar"}}

这就是为什么它显示验证错误所以删除这一行

validates :organization_id, presence: true

来自您的会员模型

同样对于@member问题,你需要这样做

@organization.memebers.each do |member|
  member.send_activation_email
end