【问题标题】:accepts_nested_attributes_for with validations and using find_or_create_by接受_nested_attributes_for 与验证并使用 find_or_create_by
【发布时间】:2016-06-03 20:14:15
【问题描述】:

我有一个user 模型和一个town 模型。 user 属于town

# models/user.rb
class User < ApplicationRecord
  belongs_to :town
  accepts_nested_attributes_for :town
  validates :last_name, presence: true
end


# models/town.rb
class Town < ApplicationRecord
  has_many :users
  validates :name, presence: true
  validates :name, uniqueness: true
end

你去创建一个新的user 记录:有一个text_box 用于放入相关城镇的name。提交后,rails 应用程序应执行以下操作:

  • 使用find_or_create_by。去检查是否已经存在带有name 属性传入的town 记录。
    • 如果town 记录与给定的name 属性存在,只需将现有的town 记录关联到这个新的user 记录
    • 如果town 记录与给定的name 属性不存在,则使用该name 属性创建一个新的town 记录,并将该记录与该user 记录相关联
  • 如果任何验证失败,请勿创建 user 记录或 town 记录并重新呈现表单。

我在这方面遇到了真正的麻烦。 This question 建议将autosave 放在belongs_to :town 语句上,并定义一个名为autosave_associated_records_for_town 的方法。但是:我就是无法让它发挥作用。

欣赏!

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    请尝试该解决方案。它对我有用。

    用户

    # user.rb
    
    class User < ActiveRecord::Base
      belongs_to :town
    
      accepts_nested_attributes_for :town
      validates :last_name, presence: true
    end
    

    城镇

    # town.rb
    
    class Town < ActiveRecord::Base
      has_many :users
      validates :name, presence: true
    end
    

    控制器

    # users_controller.rb
    
    respond_to :html    
    
    def create
    
      # ...
      @user = User.new(user_params)
      @user.town = Town.find_or_initialize_by(user_params[:town_attributes])
      if @user.save
        respond_with(@user)
      else
        render 'new'
      end
    end
    
    # ...
    
    def user_params
      params.require(:user).permit(:last_name, :email, :town_id, town_attributes: [:name])
    end
    

    查看

    # users/_form.html.erb
    
    <%= form_for(@user) do |f| %>
    
      <% if @user.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
    
          <ul>
          <% @user.errors.full_messages.each do |msg| %>
            <li><%= msg %></li>
          <% end %>
          </ul>
        </div>
      <% end %>
    
      <div class="field">
        <%= f.label :email %><br>
        <%= f.text_field :email %>
      </div>
    
    
      <div class="field">
        <%= f.label :last_name %><br>
        <%= f.text_field :last_name %>
      </div>
    
      <%= f.fields_for :town, @town do |bldr| %>
        <div class="field">
          <%= bldr.label :name, 'Town name' %><br>
          <%= bldr.text_field :name %>
        </div>
      <% end %>
    
      <div class="actions">
        <%= f.submit %>
      </div>
    <% end %>
    

    更新

    请考虑将 validates_associated 添加到用户的验证中。 这是相关的documentaion

    class User < ActiveRecord::Base
      belongs_to :town
    
      accepts_nested_attributes_for :town
      validates :last_name, presence: true
      validates :town, presence: true
      validates_associated :town
    end
    

    一般来说,在这种情况下,您可以删除 validates :town, presence: true。没有它也可以进行验证。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-03
      • 1970-01-01
      • 2013-12-24
      • 1970-01-01
      • 2012-02-10
      相关资源
      最近更新 更多