I am new at Grails and I have something to ask who is expert in Grails. I use asset pipeline as resources management in my project. Everything is good, But there is an issue that, whether my resources file (scss filess, coffee script files, ...) is changed or not, the resources are compiled every time views are rendered (in dev and test environment). This makes project run slow. Is there any solution to cache resource in asset pipeline, therefore if there is not any changing, the resources are not compiled. Thanks!
If you are using require to build a require tree and then refer the tree in your views then you can directly exclude raw resources getting pre-compiled every time by the plugin. For example:
If you have a require tree under grails-app/assets/javascripts/application.js as
//= require jquery
//= require app/models.js
//= require_tree views
//= require_self
or .coffee
#= require app/models.js
#= require test
#= require_self
#= require_tree .
And you don't want models.js getting pre-compiled everytime the view using the require tree is rendered then add the configuration as below:
grails.assets.excludes = ["app/models.js"] //app/*js for all resources under app
Above config informs the plugin to avoid the precompilation of resources and will only be compiled when the asset is referred in the view and asset has any changes.
You can find more on the Usage documentation, mainly
Optionally, assets can be excluded from processing if included by your
require tree. This can dramatically reduce compile time for your
assets.
Above config can be environment specific and can be used only for dev and test. For Production environment and/or war the pre-compilation would not matter.
environments {
development {
grails.assets.excludes = ["app/models.js"]
}
}
Related
So im going to be writing a framework that uses Rspec/Capybara and Selenium to do some automation testing on an app. Im using purely RSpec (no rails) and im having some difficulties in getting everything setup correctly.
The problem I am running into is when im trying to include page object files into my specs. Right now my directory looks like:
spec (Actual .spec files go here, spec_helper is also here)
spec/support (Page Object Files go here)
In my page object files my first problem is it can't find the Capybara DSL unless I do: include Capybara::DSL at the top of each page object file (Which apparently isn't a good idea according to the warning message it gives me)
The other problem is that including my page object files in my tests Im needing to do a require_relative to the specific file (Which is sort of a pain) otherwise it can't find the class.
Is there something in spec_helper that will fix this? Im not an expert in ruby so I assume Im missing something. The Capybara DSL problem I can't figure out either for example requiring require 'capybara/rspec' doesn't seem to help either.
You have a few options for Capybara::DSL -
Include Capybara::DSL into whatever base class you're using for your PageObjects so the Capybara methods are available in that class (as opposed to on the global object) - ie. the include Capybara::DSL goes inside the class definition - not at the top of the file.
Keep an instance of Capybara::Session in your page object instances and call all capybara methods on that session instance - #my_session.find(...), etc.
Always use Capybara.current_session when calling Capybara methods - Capybara.current_session.find(...), etc
As for the require issue -- you can either use require_relative to specify files to require based from the current file, or you use require and specify the location from the projects root (current working directory). If you have a directory of files you want loaded you can add something like the following to your spec_helper.rb to tell it to load all the files
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f }
i never use this feature.so i am reading few article on it.some confusion created in my mind after reading a article on bundle & minification. so i would like to know & clear those confusion asking here.
1) i could understand what is bundle & minification but like to know that minifaction will be done on the fly everytime or do i need to minify any js file before saving into js folder?
2) what bundle.add() does ? does it minify first and then include the file in bundle ?
3) if the file is already minified and the name is like jquery.min.js then what will happen...any error occur ?
4) if minifaction will be done on the fly then does it occur every time when different client request any page or is it one time only process ?
5) after minification minified version will be cache by server to prevent minifaction all the time ?
6)
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
// Code removed for clarity.
BundleTable.EnableOptimizations = true;
}
please have a look at this code
"~/Scripts/jquery-{version}.js"));
is it wild card use {}
7) i came to know that actaul version of js file will be served during debugging not minified version. is it true ? how could i see it my self when i will test my page from IDE?
looking for discussion. thanks
There is no need to minify files yourself.
bundles.Add in your example will do one of many things: In debug mode it will add the non-minified version of jquery (in this case, the scripts show up individually, not bundled). This is done for debugging purposes.
In non-debug mode, it will use the minified version, if one exists. If one doesn't exist, it will minify it for you and put it in the bundle... either alphabetically by file name or in the order you specified. It will also put known libraries in the top of the bundle (like jQuery) as needed.
No error, but in debug mode, .min files are not used.
One time process.
Same as 4. New bundle will be created when a file changes, with query string "v" to force client to download the new bundle. "The query string v has a value token that is a unique identifier used for caching. As long as the bundle doesn't change, the ASP.NET application will request the bundle using this token. If any file in the bundle changes [it] will generate a new token, guaranteeing that browser will get the latest bundle." source
Yes it is a version wild card to automatically create a jQuery bundle with the appropriate version of jQuery in your Scripts folder. Allows you to update versions of scripts without having to change your bundling code.
Debug mode will serve up the individual, non-minified files (and no .min files). You can test by setting BundleTable.EnableOptimizations = false; or by removing that line altogether and just running in Debug mode.
In both development and production my app seems to work fine. However, I noticed it was making some requests for CSS files that were returning with 404s.
Rails 3.1.1
Heroku "Cedar" stack
the compiled production CSS "application-b3ce81dc0178ccf6b6ac77b8bc7774ef.css" begins with..
#import url(jquery.ui.base.css);#import url(jquery.ui.theme.css);#import url("jquery.ui.core.css");#import url("jquery.ui.autocomplete.css");
namely - the files that are resulting in 404s so it looks like I'm directly requesting files that have already been compiled into the application.css
application.css.scss:
/*
*= require vendor
*= require_self
*= require_tree .
*/
#import "bootstrap";
.. some more regular CSS ..
removing the require vendor line gets rid of the duplicate requests, but also results in my site missing required styles..
Any ideas?
You cannot use the CSS import with the asset pipeline as the files are not available normally, only via their fingerprinted versions.
You need to have the correct files in your application.css (via the manifest in application.css.scss) or use the Sass helpers to put the correct asset URLs in your code.
http://guides.rubyonrails.org/asset_pipeline.html#coding-links-to-assets
I am using the assets pipeline (in Rails 3.1.3) and am kind of struggling to make it work in production.
Situation
In my /app/assets/stylesheets directory I have the following files:
application.css --> this is the default rails one
stylesheet.css --> This is my custom stylesheet
I spent a lot of time getting my stylesheet.css included in the /public/assets/directory in production (by running rake assets:precompile) and I finally made it by adding the following line into in my application.rb file:
config.assets.precompile += ['stylesheet.css']
I know have the right precompiled stylesheet.css file in production.
My Problem
The problem I have is when using stylesheet_link_tag with my stylesheet.css file. It turns out:
<%= stylesheet_link_tag "stylesheet" %> is resolved into <link href="/stylesheets/stylesheet.css" media="screen" rel="stylesheet" type="text/css"> in production I would expect the path to be resolved into /assets/stylesheet.css just like it does in development.
What is even more surprising is that application.css behaves perfectly even though <%= stylesheet_link_tag "application"%> resolves into <link href="/stylesheets/stylesheet.css" media="screen" rel="stylesheet" type="text/css">. What I don't understand is that the public/stylesheets/ directory does not exist in rails 3.1.
Any idea ?
Richard Hulse answers pointed me to the right direction. What happens is really subtle..
The answer to my question is Rails 3.1 assets has no fingerprint in production.
Basically, my project use mongoid instead of ActiveRecord. According to Mongoid documentation about configuration, the application.rb file can be modified to not include ActiveRecord which means removing:
require railties/all
And replacing it with:
require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "rails/test_unit/railtie"
# require "sprockets/railtie" # Uncomment this line for Rails 3.1+
I was so used to doing this manipulation with rails 3.0.x that I did not pay attention to the comment related to Rails 3.1
My problem was that I was not requiring sprockets !
Thank you all for your help !
The reason you can access stylesheet.css in development is because of how Sprockets works.
In development mode ALL requests to anything under /assets are sent to Sprockets to process. Sprockets will directly map requests to paths, one-to-one, so you can access any assets stored in app/assets/etc.
All requests go through Sprockets; it is serving the files to your browser.
In production things are different. A fingerprint is added to filenames, and the expectation is that you'll precompile your assets to static files. This is for performance reasons - Sprockets is not fast enough to serve lots of requests.
Only those CSS and JS files referenced by the default manifests are compiled into application.css and application.js. Other files that you reference are not precompiled unless they are added to the config.assets.precompile array in your config file.
You say that the files resolve to /stylesheets/stylesheet.css. The pipeline should generate a path like this in development: /assets/applicaton.css. In production there should be a fingerprint in the filename. What you have posted suggested that the pipeline is not enabled (these are the old, pre 3.1, locations for the files).
If this is an upgraded app, it is likely that you have missed some crucial config option. This is the main cause of dev->production issues. Check that the pipeline options are set exactly as they are in the last section of the pipeline guide. (My guess is that you are missing config.assets.enabled = true in application.rb)
And for clarity I would suggest changing the name of stylesheet.css to admin.css, while including this in the precompile array (as you already had done).
With the config options set correctly, and your admin manifest included in precompile, you should have application.css available for the front end and admin.css available for the back-end, both linkable via the helper methods.
You application.css should be a manifest file, meaning that your when you run your program it should include your stylesheet.css automatically.
make sure it has these two lines.
application.css:
/*
*= require_self
*= require_tree .
*/
If it does then something else isn't working properly, you shouldn't need the line:
config.assets.precompile += ['stylesheet.css']
If that isn't working either make sure you have all the settings enabled from this Asset Pipeline guide.
While I was looking around actionpack to see what might be causing this problem I found this little gem in the 3.1.1 changelog:
javascript_path and stylesheet_path now refer to /assets if asset pipelining is on.
Soooo, If you're using 3.1.0 upgrade to 3.1.1 and see if it fixes it. If you've already upgraded then were back to square one. But it does seem to describe your problem since stylesheet_link_tag uses stylesheet_path interally.
I have the following folder structure:
/main
/loader.php
/build.xml
/components
/package1
/class1.php
/package2
/class2.php
/tests
/package1
/class1.test.php
/package2
/class2.test.php
When I run the web application I load loader.php at first and include other components by calling Loader::load( 'package_name' ). Then all neccessary files are included. The good thing here is that I don't need to include loader.php within the class files because I can rely on having a working instance of Loader.
The Unit Test classes simulate this behaviour by including all neccessary classes explicitly. So there is also no problem with phing and PHPUnit.
But now I want to generate a coverage report with phing and Xdebug. The problem here is that phing seems to load every single PHP file to create the coverage database. Unfortunately it stops because it cannot find the Loader class that is used in the PHP files.
I could easily add an include statement to every class file, but I wonder whether there is a way to include files only if code coverage analysis is inspecting the file?
Other idea: I could also configure the coverage analysis in a way that it scans the unit tests directory and therefore finds all neccessary includes. Then I'd need to filter classes that match to a pattern like /Test$/i or so. Possible?
I looked for ages for something similar.
In the end I ended up with the changes below. Basically you tell php cli to prepend a php file which contains your loading logic.
In php.ini of my cli I've set the following:
auto_prepend_file = autoload.php
I made sure that the file was on my include path (/usr/share/php in my case) and put following lines in it (I use Zend Framework which is also on my include path):
require_once "Zend/Loader/Autoloader.php";
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('Model_');
Now, what you could do is define your __autoload function and define what needs to be autoloaded, but you get the idea.
It's an ugly hack, but it got things done for me.
Wkr
Jeroen