Erlang: هل هناك طريقة لتصدير بعض صادرات الوحدة النمطية الأخرى من الوحدة النمطية الخاصة بي؟

StackOverflow https://stackoverflow.com/questions/5051453

  •  15-11-2019
  •  | 
  •  

سؤال

أنا أكتب عدة موارد لشركة WebMachine التي تشارك الكثير من الوظائف نفسها.لذلك أنا أتساءل عما إذا كان من الممكن كتابة الوظائف الشائعة في وحدة نمطية منفصلة، ثم تضمينها بطريقة ما، وتصدر صادراتها تلقائيا بواسطة المورد (دون الحاجة إلى تصديرها من كل مورد صريح).

هل كانت مفيدة؟

المحلول

Yes you can use the mixer library, https://github.com/opscode/mixer it is a compiler parse transform that will do exactly what you want. I use it all over the place for webmachine callbacks

نصائح أخرى

We have a wrapper module that implements all Webgear callbacks and transfers them to the real implementation module if they are implemented there. That module can have special implementations for certain parts or even enable new callbacks in the modules using it. Basically that module is a wrapper resource for all your other resources.

First, your dispatch map would look as follows:

[{"/some/path", webgear_wrapper, {actual_resource, ["Some", extra, "Args"]}}].

To do this, you need to discover what callbacks your actual implementation module implements:

-record(context, {module, context, exports}).

init({Mod, Args}) ->
    {ok, Context} = Mod:init(Args),
    {ok, #context{module = Mod, context = Context, exports = exports(Mod)}}.

exports(Mod) ->
    dict:from_list(Mod:module_info(exports)).

This will initialize a basic Webgear resource that has information about the real callback module in its state.

Then, for every callback to the wrapper resource (which you must implement if you want your implementation modules to be able to use then), you would see if that function was implemented and handle it there, using this function:

call(#context{module = Mod, context = Cxt, exports = Exports},
     Func, Req, Default) ->
    case dict:is_key(Func, Exports) of
        true  -> Mod:Func(Req, Cxt);
        false -> {Default, Req, Cxt}
    end.

The call/4 function is, for example, used like this in the wrapper module:

malformed_request(Req, Cxt) ->
    % false here is the default value to return if the callback is missing
    {Res, NewReq, NewCxt} = call(Cxt, malformed_request, Req, false),
    % Now we must update the state accordingly
    {Res, NewReq, Cxt#context{context = NewCxt}}.

This works well in our project where all resources share some common logic (implemented in such a wrapper module). Haven't benchmarked the performance very much though, but the overhead should be fairly small (one dict lookup and one extra module call, plus some record wrangling).

No,it is not possible. What I did was to implement all the callbacks needed by my app to the generic function. Another way would be to patch webmachine to fetch the cb's from a function instead of by looking at exports.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top