正确地压倒适当的曝光

发布于 2024-11-17 07:56:41 字数 1351 浏览 0 评论 0原文

Rails 3.0.7 + Decent Exposure Gem

我正在为具有一个关联属性的模型创建一个表单:

class Foo
  has_many :bars

  def self.build_next(attributes={})
    if item = last.try(:clone)
      # ... overrides
    else
      item = self.new
    end

    item.attributes = attributes
    return entry
  end
end

允许用户从选择框中选择关联项之一。所以我的基本控制器如下所示:

class FooController < ApplicationController
  expose(:foos)
  expose(:foo)
  expose(:bar)

  def new
   #...
  end

  def create
    if foo.save
      redirect_to foo
    else
      render :action => 'new'
    end
  end
end

这很好用,但需要调整功能以克隆前一个项目而不是创建新项目。所以我补充道:

  default_exposure do |name|
    collection = name.to_s.pluralize
    if respond_to?(collection) && collection != name.to_s && send(collection).respond_to?(:scoped)
      proxy = send(collection)
    else
      proxy = name.to_s.classify.constantize
    end

    if id = params["#{name}_id"] || params[:id]
      proxy.find(id).tap do |r|
        r.attributes = params[name] unless request.get?
      end
    else

      # NEW CODE
      if name == :foo && params[:action] == :new.to_s
        # override
        Foo.build_next
      else
        proxy.new(params[name])
      end

    end
  end

这完全有效,但它几乎破坏了我的乐趣。它超级巨大而且非常草率。一定有更好的方法吧?

Rails 3.0.7 + Decent Exposure Gem

I'm creating a form for a model with one associated attribute:

class Foo
  has_many :bars

  def self.build_next(attributes={})
    if item = last.try(:clone)
      # ... overrides
    else
      item = self.new
    end

    item.attributes = attributes
    return entry
  end
end

The user is allowed to select from a select box one of the associated items. So my basic controller looks like this:

class FooController < ApplicationController
  expose(:foos)
  expose(:foo)
  expose(:bar)

  def new
   #...
  end

  def create
    if foo.save
      redirect_to foo
    else
      render :action => 'new'
    end
  end
end

This works great, but the functionality needs to be adjusted to clone the previous item instead of creating a new one. So I've added:

  default_exposure do |name|
    collection = name.to_s.pluralize
    if respond_to?(collection) && collection != name.to_s && send(collection).respond_to?(:scoped)
      proxy = send(collection)
    else
      proxy = name.to_s.classify.constantize
    end

    if id = params["#{name}_id"] || params[:id]
      proxy.find(id).tap do |r|
        r.attributes = params[name] unless request.get?
      end
    else

      # NEW CODE
      if name == :foo && params[:action] == :new.to_s
        # override
        Foo.build_next
      else
        proxy.new(params[name])
      end

    end
  end

This totally works, however it pretty much ruins my fun. It's super huge and is incredibly sloppy. There must be a better way right?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

静水深流 2024-11-24 07:56:41

为什么不在模型的 before 回调中而不是在控制器中执行此操作?

例如

class Foo < ActiveRecord::Base
  has_many :bars
  before_validation_on_create :build_next
  def build_next
    if prev_item = Foo.last.try(:clone)
      # ... overrides
    else
      prev_item = Foo.new
    end

    attributes.reverse_merge! prev_item.attributes 
  end
end

Why not do this in a before callback on the model instead of in the controller?

e.g.

class Foo < ActiveRecord::Base
  has_many :bars
  before_validation_on_create :build_next
  def build_next
    if prev_item = Foo.last.try(:clone)
      # ... overrides
    else
      prev_item = Foo.new
    end

    attributes.reverse_merge! prev_item.attributes 
  end
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文