Rails 5 - 从父控制器的编辑路径中排除特定实例 [英] Rails 5 - exclude specific instances from edit path on parent controller

查看:322
本文介绍了Rails 5 - 从父控制器的编辑路径中排除特定实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



用户创建提案,然后他们自己和其他人可以创建评论。

>

模型之间的关联是:

用户

<$ p $ > code> has_many:建议,依赖于:destroy
has_many:潜能

建议

  belongs_to:用户
has_many:潜能,inverse_of::建议
accep_nested_attributes_for:潜能, reject_if::all_blank,allow_destroy:true

潜在

  belongs_to:提案,inverse_of:潜力
belongs_to:用户

在我的路线文件中,我有两个潜在的资源。我不知道我是否已经用这个位移走了滑雪道 - 我无法找到如何做到这一点的例子。我有两个:

 资源:潜力

以及:

 资源:提案do 

资源:潜力

我这样做的原因是,当用户创建提案时,他们可以使用嵌套字段表单来添加潜在属性。当另一个用户看到该提案时,他们会得到一个新表单来添加:潜在的一组属性(它们不通过提案表单执行)。



在我的潜在的视图文件夹,我有意见为新的呈现形式以及potential_fields_for我的建议形式(只有提案创建者可以使用嵌套字段)。



新/渲染表单有:

 <%= simple_form_for [@proposal,@potential] do | f | %GT; 
f

提案表单包含:

 <%= f.simple_fields_for:潜能do | f | %GT; 
<%= f.error_notification%>
<%=呈现'潜在/潜在字段',f:f%>

<%end%>


<%= link_to_add_association'添加另一个新颖方面',f:电位,部分:'potentials / potential_fields'%>
< / div>

在我的提案控制器中,我试图找到一种排除第三方创建的方法:提案表单中显示的字段。

  def编辑
@ proposal.potentials_build除非@ proposal.potentials || @ proposal.potential.user_id!= current_user.id

我不希望提案创建者为能够从提案表单中编辑这些字段,但即使我没有触及它们,当我更新提案表单时(没有更新那些特定的第三方潜在属性),第三方潜在用户标识符也会更新为提案创建者标识符, 。

我尝试在提议控制器中更改编辑操作,排除不是当前用户标识的用户创建的电位。只有提案创建者可以编辑提案,因此我预计这会排除具有除proposal.user_id之外的其他用户标识的proposal.potential实例。





有没有一种方法可以将提案编辑操作限制为仅由提案创建者创建的潜在实例?



TARYN的建议



我尝试采纳Taryn对此的想法。



在我的proposal.rb中,我做了2个范围:

 范围:owner_potentials, - > {where(user_id:potential.user_id)} 
scope:third_party_potentials, - > {where(user_id:!= potential.user_id)}

我不确定这是编写范围的正确方法。尽管我无法找到如何编写它们的参考资料,但在以前我试图学习如何编写它们的时候,我收到了一些建议,以这种格式设置它们:



(user_id:potential.user_id)}
scope:third_party_potentials, - >(user){where(user_id)($ user_id){code> scope:owner_potentials, - > :!= potential.user_id)}

我也是这样试过的,但是我得到同样的错误就像我不包括(用户)一样。我不明白这些包含内容做了什么或应该做什么。



在我的提案控制器中,编辑动作,然后我尝试了以下每一项:

 #@ proposal.potentials_build unless @ proposal.potentials || @ proposal.potential.user_id!= current_user.id 
#@ proposal.owner_potentials.build除非@ proposal.owner_potentials
#@ potentials = @ proposal.owner_potentials || @ proposal.owner_potentials.build

第一个是我最初的尝试。它没有工作,并促使我写这篇文章。



第二个是我认为它应该写的方式。第三种是直接结合Taryn的想法,看看它是如何写的(尽管我认为这更多的是描述该做什么的一般方式)。 / p>

这些工作都不行。在这个尝试的第二个版本中,我收到一个错误消息:

  NoMethodError at / proposals / 17 / edit 
未定义方法`owner_potentials'for#< Proposal:0x007f84f6ca1700>

我认为这个工作没有起作用的原因是作用域作为表在类上运行,不是要编辑的具体实例。我认为这篇文章解释了这一点。

建议有很多潜力,所以我们的想法是检查属于特定提案的所有潜力,看看这些潜力中的任何一个是否具有相同的用户标识作为提案实例上的用户标识。我该怎么做?



我不能写:

 建议.owner_potentials.build除非Proposal.owner_potentials 

在提案控制器编辑操作中,因为set_proposal方法正在挑选



我可以在控制器编辑操作中使用作用域,其中has_many关系正在由作用域进行测试吗?

p>

NEXT ATTEMPT



我的下一个想法是尝试在潜能中定义范围模型,以便范围可以在类上运行。



我试过:

 范围:owner_potentials, - > { ('user_id == potential.proposal.user_id')} 
scope:third_party_potentials, - > {where('user_id!= potential.proposal.user_id')}

我在codement上花了几个小时,试图学习示波器,而我从上次会话中得到的结果是我上面使用的语法是不正确的 - 但是我显示的方式写他们(这是在帖子的顶部,给未定义的变量一个错误)。我不知道如何弄清楚如何学习编写示波器。



无论如何 - 接下来我尝试将我的Proposal控制器中的编辑动作更改为:

  @ proposal.potentials.owner_potentials.build除非@ proposal.potentials.owner_potentials 

现在,当我保存并尝试它时,我没有收到任何错误,但是当我尝试编辑提案时,我仍然可以编辑由第三方创建的潜在可能。我不明白我是否没有有效地编写范围,或者如果这个解决方案不能正常工作的话。

我会考虑添加一个自定义范围的关联,例如 owners_potentials / third_party_potentials 除了所有者之外。您可以在需要时随时使用这些范围。



例如

  has_many:potentials,inverse_of::proposal 
has_many:owner_potentials, - > {where(potentialals.user_id = proposals.creator_id)}
has_many:third_party_potentials, - > {where(potential .user_id!= suggestions.creator_id)}

然后您可以执行下列操作:

  def编辑
@potentials = @ proposal.owner_potentials || @ proposal.owner_potentials.build

然后在表单中详细说明如何使用指定的:

 <%= f.simple_fields_for @potentials do | f | %GT; 

注意:代码没有经过测试或完整性检查,在这里给出了这种类型的想法你可以做的事 - 让它实际工作留给读者练习;)


I have models in my Rails 5 app for User, Proposal and Potential.

Users create Proposals which they themselves and others can then create comments on.

The associations between models are:

User

  has_many :proposals, dependent: :destroy
  has_many :potentials

Proposal

belongs_to :user
has_many :potentials, inverse_of: :proposal
    accepts_nested_attributes_for :potentials, reject_if: :all_blank, allow_destroy: true

Potential

belongs_to :proposal, inverse_of: :potentials
  belongs_to :user

In my routes file, I have two resources for potentials. I'm not sure if I've gone off piste with this bit- I cant find an example of how to do this otherwise. I have both:

resources :potentials

as well as:

resources :proposals do

    resources :potentials

The reason I have done this is so that when the user is creating a proposal, they can use a nested fields form to add potential attributes. When another user sees that proposal, they get a new form to add a :potential set of attributes (they don't do it via the proposal form).

In my potentials view folder, I have views for new which renders form for as well as potential_fields_for which is incorporated in my proposals form (only the proposal creator can use the nested fields).

The new/render form has:

<%= simple_form_for [ @proposal, @potential ] do |f| %>
f

The proposal form has:

<%= f.simple_fields_for :potentials do |f| %>
        <%= f.error_notification %>
          <%= render 'potentials/potential_fields', f: f %>

      <% end %>


      <%= link_to_add_association 'Add another novel aspect', f, :potentials, partial: 'potentials/potential_fields' %>
      </div>

In my proposals controller, I'm trying to find a way to exclude 3rd party created :potentials from the fields displayed in the proposal form.

def edit
    @proposal.potentials_build unless @proposal.potentials || @proposal.potential.user_id != current_user.id

I don't want the proposal creator to be able to edit those fields from the proposal form but even if I don't touch them, the user id on the 3rd party potential gets updated to the proposal creator id when I update the proposal form (without updating those specific 3rd party potential attributes).

I tried to change the edit action in the proposals controller be excluding potentials created by a user that is not the current user id. Only the proposal creator can edit the proposal, so I expect that this will exclude instances of proposal.potential that have a user id other than the proposal.user_id.

That doesnt work.

Is there a way that I can limit the proposal#edit action to only those potential instances that are not created by the proposal creator?

TARYN'S SUGGESTION

I tried to adopt Taryn's thoughts about this.

In my proposal.rb, I made 2 scopes:

  scope :owner_potentials, ->{ where(user_id: potential.user_id ) }
    scope :third_party_potentials, ->{ where(user_id: != potential.user_id) }

I am not confident that this is the correct way to write a scope. Although I cant find a reference to how to write them, on previous occasions when I have tried to learn how to compose them, I have received advice to set them out in this format:

scope :owner_potentials, ->(user){ where(user_id: potential.user_id ) }
        scope :third_party_potentials, ->(user){ where(user_id: != potential.user_id) }

I tried this way as well, but I get the same error as I do if I don't include "(user)". I don't understand what that inclusion does or should do.

In my proposal controller, edit action, I have then tried each of the following:

# @proposal.potentials_build unless @proposal.potentials || @proposal.potential.user_id != current_user.id
        # @proposal.owner_potentials.build unless @proposal.owner_potentials
        #@potentials = @proposal.owner_potentials || @proposal.owner_potentials.build

The first one was my original attempt. It didnt work and prompted me to write this post.

The second one is the way I think it should be written.

The third is just incorporating Taryn's idea directly to see if that's how it should be written (although I think that was more of general way of describing what to do).

None of these work. In the case of the 2nd version of this attempt, I get an error that says:

NoMethodError at /proposals/17/edit
undefined method `owner_potentials' for #<Proposal:0x007f84f6ca1700>

I think the reason why this isnt working is that the scope is run on the class as a table, not the specific instance to be edited. I think this post explains that.

Proposals have many potentials, so the idea is to check all of the potentials belonging to the specific proposal to see whether any of those potentials have the user id that is the same as the user id on the proposal instance. How can I do that?

I cant write:

Proposal.owner_potentials.build unless Proposal.owner_potentials

in the proposal controller edit action because the set_proposal method is picking out the correct proposal for edit to apply on.

Can I use a scope in a controller edit action where there is a has_many relationship that is being tested by the scope?

NEXT ATTEMPT

My next thought is to try to define the scopes in the Potential model so that the scope can run on the class.

I tried:

scope :owner_potentials, ->{ where('user_id == potential.proposal.user_id' ) }
  scope :third_party_potentials, ->{ where('user_id != potential.proposal.user_id') }

I spent hours on codementor trying to learn scopes and my takeaway from that session is the syntax i used above is incorrect - but the way I was shown to write them (which is at the top of the post, gives an error with the undefined variable). I don't know how to figure out how to learn to write a scope.

Anyway- next I tried changing the edit action in my Proposal controller to:

@proposal.potentials.owner_potentials.build unless @proposal.potentials.owner_potentials

Now, I get no errors when I save this and try it, but when I try to edit the proposal, I can still edit potentials that have been created by third parties. I don't understand whether Im not writing the scope effectively, or if this solution isnt going to work for another reason.

解决方案

I would consider adding a custom scoped association eg owners_potentials/third_party_potentials that limits potentials to those created by the owner/ by somebody other than the owner. You can then use these scopes whenever you need them.

eg

has_many :potentials, inverse_of: :proposal
has_many :owner_potentials, ->{ where("potentials.user_id = proposals.creator_id") }
has_many :third_party_potentials, ->{ where("potentials.user_id != proposals.creator_id") }

Then you could do something like:

def edit
  @potentials = @proposal.owner_potentials || @proposal.owner_potentials.build

Then in the form, be specific about using the one you've specified:

<%= f.simple_fields_for @potentials do |f| %>

Note: code has not been tested or sanity-checked, it's here to give an idea of the kind of thing you can do - getting it to actually work is left as an exercise for the reader ;)

这篇关于Rails 5 - 从父控制器的编辑路径中排除特定实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆