【问题标题】:Rails Polymorphic association with form collection_select without nestingRails多态关联与表单collection_select没有嵌套
【发布时间】:2014-04-07 02:17:50
【问题描述】:

我的应用中有以下模型

class User < ActiveRecord::Base
has_many :articles
has_many :tour_companies
has_many :accomodations
end

class Articles < ActiveRecord::Base
belongs_to :user
belongs_to :bloggable, :polymorphic => true
end

class TourCompany < ActiveRecord::Base
belongs_to :user
has_many :articles, :as => :bloggable
end

class Accommodation < ActiveRecord::Base
belongs_to :user
has_many :articles, :as => :bloggable
end

现在我的问题是我希望登录用户能够写一篇文章并使用表单 collection_select 来选择文章应该与他/她的哪个旅游公司或住宿相关联,我该怎么做轨道4?如何从表单集合选择中选择可博客类型和 ID?我不想要嵌套资源

【问题讨论】:

    标签: ruby-on-rails-4 polymorphic-associations


    【解决方案1】:

    从 Rails 4.2 开始,这可以通过rails/globalid 处理。 Rails 的 ActiveJob 使用了这个较新的选项。它使解析和查找的设置非常简单。

    首先,检查您的Gemfile.lock 是否有globalid。对于 Rails 5,它已包含在内。

    所有的魔法都发生在模型中...

    文章型号:

    # Use :to_global_id to populate the form
    def bloggable_gid
      bloggable&.to_global_id
    end
    
    # Set the :bloggable from a Global ID (handles the form submission)
    def bloggable_gid=(gid)
      self.bloggable = GlobalID::Locator.locate gid
    end
    

    要了解它的作用,请打开rails console。玩弄gid = TourCompany.first.to_global_idGlobalID::Locator.locate gid

    现在你的代码的其余部分是库存 Rails 的东西......

    文章管理员:

    # consider building the collection in the controller.
    # For Rails 5, this would be a `before_action`.
    def set_bloggables
      @bloggables = TourCompany.all + Accomodation.all
    end
    
    # permit :bloggable_gid if you're using strong parameters...
    def article_params
      params.require(:article).permit(:bloggable_gid)
    end
    

    文章形式:

    <%= f.collection_select(:bloggable_gid, @bloggables, :to_global_id, :to_s) %>
    

    如需更多演练,Simple Polymorphic Selects with Global IDs 博客文章会很有帮助。

    【讨论】:

    • 很好的答案,我不得不去查找 try 简写 &amp;。多么棒的把戏!
    • 在 2020 年(以及使用 Rails 6),这绝对是正确的答案。谢谢!
    【解决方案2】:

    所以我终于做到了。我是这样做的 在意见/文章/_form.html.erb

    <div class="row">
    <% bloggable_collection = TourCompany.all.map{|x| [x.title, "TourCompany:#{x.id}"]} +
                              Accomodation.all.map{|x| [x.title, "Accomodation:#{x.id}]}
    %>
    <p>Select one of your listing this article is associated with</p>
    <%= f.select(:bloggable, bloggable_collection,:selected =>"#{f.object.bloggable_type}:#  {f.object.bloggable_id}" ) %>
    </div>
    

    然后在文章控制器中

    #use regular expression to match the submitted values
    def create
    bloggable_params = params[:article][:bloggable].match(/^(?<type>\w+):(?<id>\d+)$/)
    params[:article].delete(:bloggable)
    
    @article = current_user.articles.build(article_params)
    @article.bloggable_id         =  bloggable_params[:id]
    @article.bloggable_type       =  bloggable_params[:type]
    if @article.save
      redirect_to admin_root_url, :notice => "Successfully created article"
    else
      render 'new', :alert => "There was an error"
    end
    end
    

    它应该可以工作!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-27
      • 2019-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多