How to use autoload classmaps for libraries in Zend Framework 2? - zend-framework2

With the Zend Framework Tool (ZFTool) one can make the application faster, using the classmap- (instead of the namespace-) based class loading (s. here).
$ cd /path/to/my_project
$ cd module/MyModule/
$ zf classmap generate . ./autoload_classmap.php --overwrite
Is it possible / How to do the same for library modules (Zend library and custom libraries)?

The classmap generator is not specific to classes under the Zend namespace, it will generate a classmap for any classes it finds. You can pass a path to the script to get it to search your library folder instead:
zf classmap generate . ./autoload_classmap.php --overwrite --library /path/to/my_project/library
See the docs for the full list of params.

Doing this actually wouldn't be advantageous because the autoload file would simply become too big. What i can however suggest to you is to use a Module provided by Evan Coury called EdpSuperluminal.
What this Module does it, it "records" all the classes that are called within a given request and writes those into a classmap file.
The only downside to this Module is, that you'll have to create every single possible Request of your Application with a special Query-Parameter attached. That's a bit of a hassle but it's worth it. Doing it this way, you reduce the size of your Classmap to only those of the Zend Library as well as other Vendor Libraries, that you actually use. This way your classmap won't be oversized.
Other than that though, using the standard autoload_classmap.php on the /vendor directory should actually work.
And a last thing to note: Since you most likely include the Libraries (Zend, Doctrine, others...) via Composer, Composer itself creates a sort of a Classmap, but only specific to the Vendor-Namespaces. I.E "Zend", "Doctrine", "Mongo", etc.. Composer does this for the Top-Level-Namespaces only because of the above mentioned reasoning.

Related

Why do some "Plain Old Ruby Objects" go in app/models directory instead of lib direcory?

I am working on a project where the current developers have put their "Plain Old Ruby Objects" in the models directory of our Rails app.
I have seen most examples online where the PORO files go inside lib instead, but some say models.
Is there even a logical / specific reason why people put them in the models directory over the lib directory?
"Idiomatically" the models directory intended for code used to hold state. Most of the time this would be ActiveRecord subclasses corresponding to database tables. However frequently people put other stuff in the models directory. One thing often seen are code dropped here in order to take advantage of auto-reloading. (the lib dir doesn't normally auto-reload)
Based on the Getting Started Rails guide, the app/models/ directory is pretty much anything, whereas lib/ is for modules that are used across the entire app (e.g. extensions).
As #seand said, yes, one advantage is that the app/models/ directory automatically reloads, but I tend to think of it as any class that "interacts with other classes" should live in app/models/, with the only exception being a service class (which I tend to think of as "a class which manipulates the state of another class"), which I tend to put into app/services/.
I know a lot of developers would disagree with me - many I've talked to even create a separate directory namespaced to their app (e.g. if your app is named "MyBlog", they would create an app/myblog directory for any object not explicitly backed by the database, but not a module or a service class either.
That said, I think ultimately it boils down to a) personal preference and b) where you feel is best to place the PORO with respect to your app.
There is no hard and fast rule on where to put POROs. The rails community has been hashing this out for a while now. At one point the convention was to put stuff in the concerns directory but that seems to have fallen out of favor with some folks.
One rule of thumb for the difference between /lib and app/{blah} is that code in the /lib folder is code that you presumably can reuse across several projects e.g. general purpose class or utilities. for example if you have some custom monkey patches to core ruby or rails classes that you will use in multiple projects, a good place to but them would be in the lib folder. Anything in app/{blah} should pertain specifically to current project.
One way to think of lib folder is as the poor cousin of plugins and gems.
Just my 2 cents on the subject

ZF2: When would you use autoload_classmap.php

Reading through the zf2 getting start guide and I was confused about this part:
*As we are in development, we don’t need to load files via the classmap, so we provide an empty array for the classmap autoloader. Create a file called autoload_classmap.php under zf2-tutorial/module/Album:*
<?php
return array();
Why don't we need autoload_classmap because we are in development? I read the doc on autoload_classmap.php, but still don't understand what its really for and why it would be necessary in production.
What is a classmap used for?
A classmap is basically a functionality for your application to load all relevant classes faster. This is due to the fact that every single class is assigned the full filepath and filename. Other than the standard autoloader which only maps namespaces to directories.
Why not use it during development?
The answer is simple: constantly renewing the classmap during development phase is a huge p.i.t.a. Just use the standard autoloader during development and once your module is finished, create the classmap and use it. You'll notice a slight speed boost.
Are there alternatives to using ZF2s classmap?
Yes there are. Other than having multiple classmaps for all modules it's even better if you just create ONE ENORMOUS CLASSMAP for all modules, vendor modules, libraries, etc... The solution to this is called composer

Zend Framework 2: Autoload classmap

I generated the classmap of our project to improve its performance in production.
I'm surprised because the generated file is really big (more than 5000 lines). It includes the whole ZF2 library, Doctrine, etc.
Is it normal or should I exclude the vendor directory?
EDIT:
#Sam, yes we are using APC in production.
My plan is to automatically generate the class map as part of the deployment process.
I suppose you're talking about the classmap autoloader provided by composer? Then yes, this is absolutely normal. The classmap generated for each module should only contain the modules classes tho.
As far as performance is concerned, that's a bit of a tricky thing. If you do not have access to APC or Memcache (or any other memory cache for that matter), then a 5000 Lines classmap loader will probably not be the most ideal solution.
The most ideal solution would be a classmap that ONLY contains the autoloading directives for the classes that you actually use throughout your project. Luckily Evan ".pro" Coury has created the very great EdpSuperluminal. That one does precisely what the ideal solution is all about, but it requires quite a bit of manual attention, since basically once your project is done you'll need to call every single URL of your application once with a special URL parameter to create the classmap.

Why is there Rails.rb files all over the place?

Was digging around my Rails applications and noticed that there are rails.rb files all over the place. In my ruby gems directories like:
...gems\devise-2.0.4\lib\devise\rails.rb
...gems\cucumber-rails-1.3.0\lib\cucumber\rails.rb
...gems\railties-3.2.3\lib\rails.rb
I am assuming that there are executed whenever you issue some command like "rails xxx". So all these extra rails.rb files combine with the original rails.rb file to essentially make one big rails.rb file. Essentially, when we type in "rails xxx" it goes thru all them all?
Just looking for some confirmation PLUS a little more knowledge about this. Thanks.
The best way to understand what these rails.rb files are doing, is to read the source code.
ralties
devise
cucumber-rails
As you can see, in any library the file assumes a different scope. The common behaviour is that the file rails.rb normally contains the code required to initialize the library when loaded from a Rails project.
BTW, this has nothing to do with the script/rails command and there is no "big rails.rb" file.
The files are not generated but are simply source files of these libraries you are using.
In this case they are probably rails-related classes that either extend Rails in some way or modify it or make the library interact with Rails.
Rails is a very common framework in Ruby land so most if not all libraries will have some sort of integration with Rails.
By no means are all of those loaded when you run rails XXX but rather when your application loads these libraries their rails.rb files may be executed to provide some sort of integration with Rails.

Does it make sense to create a Ruby gem that consists of only Rails template partials?

I'm trying to understand what does and doesn't work in Ruby gems (primarily from the perspective of creating one for myself to reuse functionality from one project to the next).
When you create a Ruby gem, are you limited to including only Ruby functionality or could you create a gem that consisted of Rails templates, CSS files and JavaScripts?
If so, how would the user of the gem access those resources in a Rails project (besides adding a 'config gem' statement to the environment.rb file?
No it doesn't. Gems are code libraries, not static files.
When you load a gem, you don't move the files to your public directory. You load a ruby file and get access to a module. So, you can only execute ruby code within it.
But, your ruby code can give you some helpers allowing you to easily build your design for example.
If you want to include some static file resources in each of your ruby projects, I'd see two solutions:
Create a template project, including all the css, javascript etc. that you use every time. You can take suspenders as an example of this.
Create a new repository with all these static files and add it as a submodule (with git or svn) and include it in each of your projects.
The first solution would be my favorite, but you might want to take the other one.
As dmathieu notes, gems are for ruby libraries that are installed in the system load path, not for things that go into your project directory. If you do want to package your rails project skeleton as a gem, though, it would be simple enough to have a small ruby executable that served as a generator to copy the skeleton project tree into a target directory. You could then package the whole thing up into a gem, your skeleton files could sit in the gem directory, and you could say generate_new_project someproject to copy them into your new project directory.
You can easily add partials and other HAML, Builder, or ERB views. The following structure should work:
# in my_gem/rails/init.rb
ActionController::Base.append_view_path(File.expand_path(File.join(File.dirname(__FILE__), '..', 'views')))
# in my_gem/views/my_gem/_some_partial.html.erb
This is a partial from MyGem!
# in your_rails_app/views/some_controller/some_view.html.erb:
<%= render :partial => '/my_gem/some_partial' -%>
That doesn't directly answer your question about static files, though. Often the best bet is a generator that copies the CSS, JS, and other files to your public directory. Alternatively, you could use a StaticFilesController and put the static files in that views directory.

Resources