在has_many通过关系中为through设置Rails Controller

时间:2016-03-02 10:22:22

标签: ruby-on-rails ruby

我正在创建一个带有多对多直通模型的rails web应用程序。该应用程序允许用户使用许多预定义的小部件填充他们的仪表板"。所以我有一个用户表(由设计创建和管理)和一个小部件表。都好。因此,为了管理通过位,我有一个" subscriptons"的表。这是我的模特:

class Subscription < ActiveRecord::Base
  belongs_to :user
  belongs_to :widget
  validates_uniqueness_of :user_id, scope: :widget_id
end

class User < ActiveRecord::Base
  has_many :subscriptions
  has_many :widgets, through: :subscriptions
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end

class Widget < ActiveRecord::Base
  has_many :subscriptions
  has_many :users, through: :subscriptions
end

但是,我并不真正了解如何创建订阅。理想情况下,我希望创建表单只有一个选择器可以从所有可用的小部件中进行选择,然后使用当前的user:id,但我不确定这是如何工作的,这是我的控制器:

  def new
    @subscription = Subscription.new
  end

  def create
    @user = current_user
    @subscription = @user.subscriptions.build(subscription_params)

    respond_to do |format|
      if @subscription.save
        format.html { redirect_to @subscription, notice: 'subscription was successfully created.' }
        format.json { render :show, status: :created, location: @subscription }
      else
        format.html { render :new }
        format.json { render json: @subscription.errors, status: :unprocessable_entity }
      end
    end
  end

我真的很感激能够朝着正确的方向努力,因为我无法理解这是如何从官方文档中完成的,并且找不到任何与此相关的好教程。

2 个答案:

答案 0 :(得分:2)

Assuming you don't have any other attributes on subscriptions you can use the widget_ids= method that your has_many creates on user

Controller

class UserSubscriptionsController
  def edit
    @user = current_user
  end

  def update
    @user = current_user
    if @user.update(user_subscription_params)
      redirect_to @user, notice: "Subscriptions updated"
    else
      render :edit
    end
  end

  private

  def user_subscription_params
    params.require(:user).permit(widget_ids: [])
  end
end

View

<%= form_for @user, url: user_subscription_path, method: :patch do |f| %>
  <%= f.collection_check_boxes :widget_ids, Widget.all, :id, :name %>
  <%= f.submit %>
<% end %>

The routes in my example would have

resource :user_subscription, only: [:edit, :update]

But obviously you can amend based on what you want your routes to be. Rails will automatically create the subscriptions when updating the user.

You could instead just use the collection_check_boxes when editing a user normally if you wanted. There is also collection_select

Docs

答案 1 :(得分:0)

You can save data like this using subscription form.

  = form_for @subscription do |f|
   = f.select :widget_id, options_from_collection_for_select(Widget.all, "id", "title"), {}, {:class => "form-control select" }
   = f.hidden_field :user_id, :value => current_user.id
   #other subscription fields
   = f.submit