Overriding Decent Exposure Properly
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 &&am开发者_如何学运维p; 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?
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
精彩评论