Rails中STI的RESTful routes问题
不解释,你是知道STI的——single table inheritance,我们看下问题是什么
现在有两个Model:Asset和Image
class Asset < ActiveRecord::Base; end class Image < Asset; end
我们定义了这样一个RESTful routes
resources :assets
然后在我们的AssetsController里面
class AssetsController < ApplicationController def create @asset = Asset.new params[:asset] @asset.save respond_with(@asset) end def update @asset.update_attributes params[:asset] end end
当@asset是一个Asset而不是Image时,一切正常,不过当@asset是Image时。。。
我们如果创建一个新的Image对象,便会收到这样的错误
undefined method `image_url' for #<AssetsController:0xb495718>
分析下错误来源,Rails中这些url_helpers都是依靠polymorphic_path生成的,它会检测当前model是哪一类的对象,很显然@asset是一个Image,于是就杯具的生成了一个image_url方法,这一切都是因为polymorphic_path不懂的向上继续寻找
我觉得理想的状态应该是先寻找image_url,如果没有就继续找它的superclass,也就是asset_url
这里有一个ticket,其中给出了一个Rails2的patch,那我只好自己来给Rails3做补丁了
找到action_controller/polymorphic_routes.rb,然后你懂的
def build_named_route_call(records, inflection, options = {}) unless records.is_a?(Array) record = extract_record(records) route = '' else record = records.pop route = records.inject("") do |string, parent| if parent.is_a?(Symbol) || parent.is_a?(String) string << "#{parent}_" else string << RecordIdentifier.__send__("plural_class_name", parent).singularize string << "_" end end end if record.is_a?(Symbol) || record.is_a?(String) route << "#{record}_" action_prefix(options) + route + routing_type(options).to_s else record_class = record.class named_route = build_candidate_named_route_call(route, record_class, inflection, options) until(respond_to?(named_route) || record_class.superclass == ActiveRecord::Base) do record_class = record_class.superclass named_route = build_candidate_named_route_call(route, record_class, inflection, options) end named_route end end private def build_candidate_named_route_call(route, record_class, inflection, options) origin = route.dup origin << ActionController::RecordIdentifier.__send__("plural_class_name", record_class) origin = origin.singularize if inflection == :singular action_prefix(options) + origin + "_" + routing_type(options).to_s end
如此,我们就可以很爽的使用asset_url了,管你是不是个Image
还有就是我们update一个@asset时,如果这个@asset又不幸的是一个Image,那些很有用的form_helpers生成的表单就会是类似这样的
<input name="image[title]" id="image_title" />
是的,我们的AssetsController就无法得到params[:asset],而是一个很杯具的params[:image]
我没找到什么好的解决方案,只好给AssetsController加了一个before_filter
def justify_params if params[:image] params[:asset] = params[:image] elsif params[:raw] params[:asset] = params[:raw] end end
都结束了,奖励那些看完这篇烂文的人,也就是我了^ ^
本文基于 署名-非商业性使用-禁止演绎 2.5 中国大陆 发布
4 COMMENTS >>LEAVE<<
-
我表示我只是来看看美女
-
@aoyoo
你是不是应该弄个头像了--
-
MM很漂亮
-
我一直拉~直到最后的时刻,停下了。。。
