【问题标题】:Rails update attribute when dealing with through relationships通过关系处理时Rails更新属性
【发布时间】:2018-08-13 15:29:09
【问题描述】:

我正在尝试更新显示页面上的属性,将其保留在显示页面中,该属性通过不同的表连接。例如:经理登录到管理站点并查看多个资源,单击一个并可以查看有权访问该资源的所有用户(已批准或待处理)。他们目前可以删除用户的访问权限。我正在尝试做的是允许经理将请求的状态从待处理更改为已批准。

所以对于我的模型,我有以下内容:

class TrainingResource
  has_many :user_training_resources, dependent: :destroy
end

class UserTrainingResource
  belongs_to :user
  belongs_to :training_resource
 enum status: [:pending, :confirmed, :rejected]

end

class Users
  has_many :user_training_resources, dependent: :destroy
  has_many :training_resources, through: :user_training_resources
end

TrainingResourcesController

class Admin::TrainingResourcesController < Admin::ApplicationController
  belongs_to_app :training_resources
  add_breadcrumb 'Training Resources', :admin_training_resources_path
  before_action :load_training_resource, only: [:show, :edit, :update, :destroy]
  respond_to :html, :json

  def index
    @training_resources = TrainingResource.paginate(page: params[:page])
    @training_resources = @training_resources.search(params[:search]) if params[:search]
    respond_with(@training_resources)
  end

  def show
    respond_with @training_resource
  end

  def new
    @training_resource = TrainingResource.new
    respond_with(@training_resource)
  end

  def create
    @training_resource = TrainingResource.new(training_resource_params)
    flash[:notice] = 'TrainingResource created successfully' if @training_resource.save
    respond_with @training_resource, location: admin_training_resources_path
  end

  def edit
    respond_with(@training_resource)
  end

  def update
    flash[:notice] = 'TrainingResource updated successfully' if @training_resource.update(training_resource_params)
    respond_with @training_resource, location: admin_training_resources_path
  end

  def destroy
    flash[:notice] = 'TrainingResource deleted successfully' if @training_resource.destroy
    respond_with @training_resource, location: admin_training_resources_path
  end

  private

  def load_training_resource
    @training_resource = TrainingResource.find_by!(id: params[:id])
  end

  def training_resource_params
    params.require(:training_resource).permit(:name, :description, :total_subscriptions, :url)
  end
end

UserTrainingResourcesController,它指向的是TrainingResourcesController

class Admin::UserTrainingResourcesController < Admin::ApplicationController
  belongs_to_app :training_resources
  add_breadcrumb 'Training Resources', :admin_training_resources_path
  before_action :load_training_resource
  respond_to :html, :json

  def edit
    respond_with @user_training_resource
  end

  def update 
    flash[:notice] = 'UserTrainingResource updated successfully' if @user_training_resource.update(user_training_resource_params)
    respond_with @user_training_resource, location: admin_training_resources_path
  end

  def destroy
    flash[:notice] = 'UserTrainingResource deleted successfully' if @user_training_resource.destroy
    respond_with @user_training_resource, location: admin_training_resources_path
  end

  private

  def load_training_resource
    @user_training_resource = UserTrainingResource.find_by!(id: params[:id])
  end

  def user_training_resource_params
    params.require(:user_training_resources).permit(
  :training_resources_id, :status).merge(user_id: current_user_id)
  end

end

培训资源展示

  <tbody>
    <% @training_resource.users.each do |training| %>
      <tr>
        <td><%= training.full_name %></td>
        <% utr = training.user_training_resources.where(training_resource: @training_resource).first %>
        <td><%= utr.status.capitalize %>
          <%= form_tag '/user_training_resource/edit', :method => :get do %>
            <%= select_tag( :user_training_resources_id, options_for_select(['pending', 'confirmed', 'rejected']))%>
            <%= submit_tag 'Edit Status', class: 'btn btn-default btn-sm' %>
        <% end %>

        <%= tb_form_for [:admin, @training_resource], :remote => true, :data => {:errors => :inline, :success => admin_user_training_resources_path} do |f| %>
          <%= tb_form_errors(f.object, :base) %>
          <%= f.tb_select :name, options_for_select(holder, :status) %>
          <%= f.tb_save_buttons('User Training Resource', admin_user_training_resources_path) %>
        <% end %>
        </td>
        <td class="table-actions">
          <%= link_to 'Edit', edit_admin_user_training_resource_path(training), :class => 'btn btn-default btn-sm' %>
          <%= link_to 'Delete', admin_user_training_resource_path(training), :method => :delete, :data => {:confirm => 'Are you sure you want to delete this?'}, :class => 'btn btn-danger btn-sm'  %>
        </td>
      </tr>
    <% end %>
  </tbody>

用户培训资源助手,Holder Method

  def holder
    TrainingResource.all.each(&:id)
  end

我最终会删除指向 Edit 的链接,因为它会将用户推送到 UserTrainingResource 编辑页面,并且我想将其保留在当前页面上。带有 select_tag 的顶部表单实际上并没有在当前状态下读取,然后 submit_tag 正在重定向页面。

我最近的尝试是底部form_for。这是在拉入 TrainingResource 而不是 UserTrainingResource 数据。当我将 tb_select 更改为 :status 时,options_for_select(holder, :status) 我最终得到了未定义的方法“status”。看起来它只针对 TrainingResource。我也试过:

这里认为它会拉入默认状态,然后允许更改选项。 'status'的未定义方法仍然存在问题,即使那样保存也存在问题。

我也试过了:

在这种情况下,我最终得到了未定义的方法“map”。我试图通过在 @training_resource 和 @user_training_resource 上尝试复数来确定这一点,但结果是表单中的第一个参数不能包含 nil 或为空。

编辑:

在 UserTrainingResourcesController 中尝试过:

def set_to_confirmed
 @user_training_resource = UserTrainingResource.find(params[:user_training_resource])
end

然后在节目中

              <%= link_to 'Confirmed', {:controller => 'user_training_resources', :action => 'set_to_confirmed', :status => @training_resource.user_training_resource }, :class => 'btn btn-default btn-sm'%>

虽然点击我得到的链接时页面加载没有错误:

Requested URL: https://localhost:3000/admin/set_to_confirmed?status=%23%3CUserTrainingResource%3A%3AActiveRecord_Associations_CollectionProxy%3A0x00007f93ee8b0f90%3E

使用以下内容的最新尝试:

        <% @training_resource.spud_users.each do |training| %>
      <tr>
        <td><%= training.full_name %></td>
        <% utr = training.user_training_resources.where(training_resource: @training_resource).first %>
        <td>
             <%= tb_form_for [:admin, @training_resource], :remote => true, :data => {:errors => :inline, :success => admin_training_resources_path} do |f| %>
               <%= f.select(:user_training_resource_id, options_for_select(['pending', 'confirmed', 'rejected']), :selected => utr.status)%>
               <%= f.tb_save_buttons('', admin_training_resources_path) %>
             <% end %>
        </td>

这将只显示选项,这很好,但我需要将其默认为数据库中的当前内容并且保存不粘。

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    如果我明白了,您需要更新联接表UserTrainingResource 更改状态列。

    我可能会在Admin::UserTrainingResourcesController 中创建三个动作:

    def set_to_pending
    end
    
    def set_to_confirmed
    end
    
    def set_to_rejected
    end
    

    然后我将在TrainingResource#Show 中的表格中的每一行添加三个链接,传递必要的参数来完成操作,就像这篇文章中解释的那样:pass parameter by link_to ruby on rails

    【讨论】:

    • 我确实需要更新连接表,使其能够更改状态列。所以我实际上输入了以下内容: 'user_training_resources', :action => 'set_to_confirmed', :status => @training_resource.user_training_resource }, :class=> 'btn btn -默认 btn-sm'%>.放入方法,更新路由后,单击链接时会出现 404 Not Found。还有一个主要的烦恼是它将是三个按钮,而不是说一个下拉和保存。
    • 您也可以根据需要使用下拉列表发布到操作update_status,这会触发基于参数的三个操作之一。这也很有用:stackoverflow.com/questions/13414663/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-01
    • 2010-09-20
    相关资源
    最近更新 更多