繁体   English   中英

Rails-正确/更好的方式来建立一个belongs_to / has_many关系

[英]Rails - Right / Better way to to a belongs_to / has_many relationship

我正在创建一个应用程序,用户可以通过该应用程序创建一个帐户。 当他们以相同的形式创建帐户时,他们将能够创建一个组织,然后将其绑定到其用户。 一旦该用户创建了他们的帐户(和组织),其他用户将能够创建一个帐户并使用“访问码”加入该组织。 查看代码可能会更好地解释它。

我之所以在SO上发布,是因为我感觉有比目前正在做的更好/更有效的方法。 我正在使用nested_forms(可能不正确),并且我认为我没有以正确的方式进行关联,因为例如,我无法获得编辑表单来填写组织字段。

我也在使用魔术进行身份验证。

users_controller.rb

def new
  @user = User.new
end

def create
  @user = User.new(user_params)
  if params[:user][:organization][:name].blank?
    flash.now[:error] = "You must specify an organization name."
    render :new
  else
    if params[:user][:organization][:access_code].blank?
      # create new organization
      @access_code = "#{SecureRandom.urlsafe_base64(16)}#{Time.now.to_i}"
      @organization = Organization.create(:name => params[:user][:organization][:name], :access_code => @access_code)
      @user.organization_id = @organization.id
      @user.is_admin = true
    else
      # try and add someone to an organization
      @organization = Organization.find(:all, conditions: ["name = ? AND access_code = ?", params[:user][:organization][:name], params[:user][:organization][:access_code]])
      if @organization.empty?
        flash.now[:error] = "No organization has been found with that name and access code."
        render :new
        return
      else
        @user.organization_id = @organization.first.id
      end
    end
    if @user.save
      user = login(@user.email, params[:user][:password])
      if user
        flash[:success] = "Your account has been successfully created!"
        redirect_to admin_dashboard_path
      end
    else
      flash.now[:error] = "Something went wrong! Please try again."
      render :new
    end
  end
end

def edit
  @user = User.find(params[:id])
end

def update
  @user = User.find(params[:id])
  if @user.is_admin?
    if params[:user][:organization][:name].blank? && params[:user][:organization][:name] != @user.organization.name
      params[:user][:organization][:name] = @user.organization.name
    end
    if params[:user][:organization][:access_code].blank? && params[:user][:organization][:access_code] != @user.organization.access_code
      params[:user][:organization][:access_code] = @user.organization.access_code
    end
    @organization = Organization.find(params[:user][:organization_id])
    @organization.name = params[:user][:organization][:name]
    @organization.access_code = params[:user][:organization][:access_code]
    @organization.save
  end
  if @user.update(user_params)
    flash[:success] = "Your settings have been updated!"
    redirect_to edit_admin_user_path(@user.id)
  else
    flash.now[:error] = "Something went wrong! Please try again."
    render :edit
  end
end

private
  def user_params
    params.require(:user).permit(:organization_id, :email, :password, :password_confirmation, :full_name, :remember_me, {:organization_attributes => [:name, :website, :description, :access_code]})
  end

users.rb的

class User < ActiveRecord::Base
  authenticates_with_sorcery!

  belongs_to :organization

  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  validates_presence_of :full_name
  validates_presence_of :email
  validates_uniqueness_of :email, :on => :create
  validates_format_of :email, :with => VALID_EMAIL_REGEX, :on => :create
  validates_presence_of :password, :on => :create
  validates_confirmation_of :password
end

organization.rb

class Organization < ActiveRecord::Base
  authenticates_with_sorcery!

  has_many :users, :dependent => :destroy

  accepts_nested_attributes_for :users

  validates_presence_of :name
end

new.html.erb

<% provide(:title, 'Create a User') %>

<h1>Create a User</h1>
<p>Use the form below to create an account.</p>
<%= nested_form_for([:admin, @user], html: {role: "form"}) do |f| %>
  <%= render "shared/error_messages", obj: @user %>
  <fieldset>
    <legend>User Information</legend>
    <div class="form-group">
      <%= f.label :full_name, "Full Name" %>
      <span class="help-block">How should others see you?</span>
      <%= f.text_field :full_name, class: "form-control" %>
    </div>
    <div class="form-group">
      <%= f.label :email %>
      <span class="help-block">Your email address is used as your login.</span>
      <%= f.text_field :email, class: "form-control" %>
    </div>
    <div class="form-group">
      <%= f.label :password %>
      <%= f.password_field :password, class: "form-control" %>
    </div>
    <div class="form-group">
      <%= f.label :password_confirmation, "Confirm Password" %>
      <%= f.password_field :password_confirmation, class: "form-control" %>
    </div>
  </fieldset>
  <%= f.fields_for :organization do |o| %>
    <fieldset>
      <legend>Associated Organization</legend>
      <div class="form-group">
        <%= o.label :name, "Organization Name" %>
        <span class="help-block">This is the name of the organization you are a part of.</span>
        <%= o.text_field :name, class: "form-control" %>
      </div>
      <div class="form-group">
        <%= o.label :access_code, "Organization Access Code" %>
        <span class="help-block">Leaving this field blank will setup a new organization.</span>
        <%= o.text_field :access_code, class: "form-control" %>
      </div>
    </fieldset>
  <% end %>
  <div class="form-actions">
    <%= f.submit "Create Account", class: "btn btn-primary" %>
    <%= link_to "Cancel", :back, class: "text-btn" %>
  </div>
<% end %>

edit.html.erb

<% provide(:title, "Edit User: #{@user.full_name} (#{@user.organization.name})") %>

<h1>Edit User: <%= @user.full_name %> (<%= @user.organization.name %>)</h1>
<p>Use the form below to manage your account.</p>
<%= nested_form_for([:admin, @user], html: {role: "form"}) do |f| %>
  <%= render "shared/error_messages", obj: @user %>
  <fieldset>
    <legend>User Information</legend>
    <div class="form-group">
      <%= f.label :full_name, "Full Name" %>
      <span class="help-block">How should others see you?</span>
      <%= f.text_field :full_name, class: "form-control" %>
    </div>
    <div class="form-group">
      <%= f.label :email %>
      <span class="help-block">Your email address is used as your login.</span>
      <%= f.text_field :email, class: "form-control" %>
    </div>
    <div class="form-group">
      <%= f.label :password %>
      <%= f.password_field :password, placeholder: "leave blank to keep password unchanged", class: "form-control" %>
    </div>
    <div class="form-group">
      <%= f.label :password_confirmation, "Confirm Password" %>
      <%= f.password_field :password_confirmation, class: "form-control" %>
    </div>
  </fieldset>
  <% if @user.is_admin? %>
    <%= f.fields_for :organization do |o| %>
      <fieldset>
        <legend>Associated Organization</legend>
        <div class="form-group">
          <%= o.label :name, "Organization Name" %>
          <span class="help-block">This is the name of the organization you are a part of.</span>
          <%= o.text_field :name, class: "form-control", value: @user.organization.name %>
        </div>
        <div class="form-group">
          <%= o.label :access_code, "Organization Access Code" %>
          <span class="help-block">Leaving this field blank will setup a new organization.</span>
          <%= o.text_field :access_code, class: "form-control", value: @user.organization.access_code %>
        </div>
      </fieldset>
    <% end %>
    <%= f.hidden_field :organization_id %>
  <% end %>
  <div class="form-actions">
    <%= f.submit "Update User", class: "btn btn-primary" %>
    <%= link_to "Cancel", :back, class: "text-btn" %>
  </div>
<% end %>

好的,所有这些文件都可以实现。 现在,我的应用程序几乎可以完成我需要做的所有事情,但这对我来说并不像生产级代码。

我知道我遇到的一个问题是,如果用户在“组织”字段中键入内容,而控制器没有其他任何内容,控制器将创建并保存组织,然后使用用户验证错误将表单呈现回去。 如果用户模型中存在验证错误,我不希望它保存组织。

我真的只是在寻求建议,如果有更好的方法来做我想做的事情。 如果您无法确切说明我要使用此代码做什么或有任何疑问,请告诉我!

看看这篇文章: http : //blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/

特别有趣的是“ 3.提取表单对象”部分。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM