【问题标题】:has_many through create relationship from existing modelshas_many 通过从现有模型创建关系
【发布时间】:2015-07-06 16:11:13
【问题描述】:

我有一个市场,我的用户可以在其中创建计划,他们的客户可以加入他们。所以我有一个计划模型和一个客户模型。最终目标是为客户订阅计划,因此我创建了一个订阅模型和一个 has_many :through 关联,但我需要一些帮助才能使创建正常工作。在订阅能够发生时,计划和客户已经存在,因此我无需担心在订阅#create 上创建计划或客户,我只需要担心加入现有的计划或客户。

我现在所处的位置是创建订阅模型,但它没有关联到正确的客户。我需要为我订阅该计划的每个客户创建一个订阅模型,并且我正在使用多选标签。

我使用 has_many :through 因为一个计划有很多客户,但一个客户也可以有很多计划。

如果有什么不清楚的地方请告诉我,我试图尽可能清晰简洁地解释它。

计划模型

class Plan < ActiveRecord::Base
    has_many :subscriptions
    has_many :customers, through: :subscriptions
end

客户模型

class Customer < ActiveRecord::Base
    has_many :subscriptions
    has_many :plans, through: :subscriptions, dependent: :delete_all
end

订阅模式

class Subscription < ActiveRecord::Base
    belongs_to :plan
    belongs_to :customer
end

Routes.rb

  resources :customers
  resources :plans do
    resources :subscriptions
  end

订阅控制器

class SubscriptionsController < ApplicationController

    def new
        @user = current_user
        @company = @user.company
        @plan = Plan.find(params[:plan_id])
        @subscription = Subscription.new
    end

    def create
        if @subscription = Subscription.create(plan_id: params[:subscription][:plan_id] )
            @subscription.customer_id = params[:subscription][:customer_id]
            @subscription.save
            flash[:success] = "Successfully Added Customers to Plan"
            redirect_to plan_path(params[:subscription][:plan_id])
        else
            flash[:danger] = "There was a problem adding your customers to this plan"
            render :new
        end
    end
    private

    def subscription_params
        params.require(:subscription).permit(:customer_id, :plan_id, :stripe_subscription_id)
    end
end

表格:

    <%= form_for [@plan, @subscription] do |f| %>
    <%= f.hidden_field :plan_id, value: @plan.id %>
    <div class="row">
        <div class="col-md-6">
            <%= f.select :customer_id, options_from_collection_for_select(@company.customers, 'id', 'customer_name', @plan.customers), {}, multiple: true, style: "width: 50%;" %><br />
        </div>
        <div class="col-md-12">
            <%= f.submit "Add Customer To Plan", class: "btn btn-success pull-right" %>
        </div>
    </div>
    <% end %>

参数:

{"utf8"=>"✓",
 "authenticity_token"=>"###",
 "subscription"=>{"plan_id"=>"5", "customer_id"=>["", "153", "155"]},
 "commit"=>"Add Customer To Plan",
 "action"=>"create",
 "controller"=>"subscriptions",
 "plan_id"=>"5"}

【问题讨论】:

  • 你可以用@subscription = Subscription.create(params[:subscription])替换这个@subscription = Subscription.create(plan_id: params[:subscription][:plan_id] )
  • @MaxWilliams 当我尝试这样做时,我得到了一个严重的参数错误,说禁止属性。当我做Subscription.create(subscription_params) 时,我遇到了与客户无关的同样问题。

标签: ruby-on-rails ruby-on-rails-4 activerecord has-many-through nested-resources


【解决方案1】:

params[:subscription][:customer_id] 是一个数组:

 "subscription"=>{"plan_id"=>"5", "customer_id"=>["", "153", "155"]},

您是否真的尝试在计划和此数组中的每个客户之间建立订阅?如果是这样,请尝试调用 @plan 对象的更新方法,在 params[:plan][:customer_ids] 中传递这些(注意 s)

编辑:

当我说“通过 params[:plan][:customer_ids] 中的 ids”时,我希望您执行标准控制器行为以进行更新,这类似于

@plan = Plan.find(params[:plan_id])
@plan.update_attributes(params[:plan])

如果params = {:plan =&gt; {:customer_ids =&gt; [1,2,3]}} 那么上面的代码会这样做:

@plan.update_attributes({:customer_ids => [1,2,3]})

这就像说

@plan.customer_ids = [1,2,3]
@plan.save

当你建立一个关联时,你会得到很多可以在对象上调用的方法。其中一个是&lt;association&gt;_ids,在本例中为customer_ids,这是一种设置关联的方式:当您保存时,它将使@plan 与客户1,2 & 3 之间建立关联。

你正在这样做:

@plan.customers << params[:plan][:customer_ids]

这将客户记录与 ID 混合在一起。如果你要使用push,又名&lt;&lt;,你需要推入客户对象,而不是ID。仅使用customer_ids = 是一种更快捷、更简单的方法。

【讨论】:

  • 这正是我想要做的。我尝试通过执行@plan.customers &lt;&lt; params[:plan][:customer_ids] 然后@plan.save 将其更改为计划更新操作,但我不断收到“ActiveRecord::AssociationTypeMismatch”错误,所以我不确定我在这里做错了什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-15
相关资源
最近更新 更多