Difficult code packaging design [closed] - ruby

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I've built a tool to write college curricula using the static site generator nanoc. Nanoc is a nice Ruby-based package and it is distributed as a gem.
I installed the gem, and used the "nanoc new" command to create the basic directory structure. Within that directory structure I wrote some custom ruby code, as well as a large number of markdown files to define my first course. Here's the course as it is built.
The code I showed above, in git, corresponds to the result of that work, nanoc + my customizations. There's a bundler file that has to be run to bring in my additional gems as well.
Let's call the individual course "cosi235a.course" and let's call my tool "nanoc-course". I will call the author of cosi235a.course "an author" and I will call the maintainer of "nanoc-course" "me".
What I am seeking help with is a nice design to decouple nanoc-course from cosi235a.course. In other words, I want to separate my customized nanoc based tool from the content of one course.
That way if I want to design the curriculum for a second course I can create that and still pull in updates to the common code. More than that, another author could create a new course on their site, and use nanoc-course for themselves, and benefit from updates I make to the tool.
I've been turning this design question over in my mind and I am not finding an idea I like. Here are the ideas, half baked, so far:
Make nanoc-courss on Git contain everything except all the Markdown, HTML, and other content files. They happen to all live in a subdirectory called ./content according to nanoc. The directory is empty on Git. Add some Rake tasks to create symlinks to a separate directory containing cosi235a.course files. This way the author can work on their content files and at any time do a git pull to any updates to nanoc-course. This is a clean separation but is clunky.
Make nanoc course be a gem to be used with nanoc. In other words, the author installs nanoc, does a gem install (or bundler install) of nanoc-course and add a line or two into nanoc's libs to incorporate the logic. This separation is less complete and requires the author (who is not necessarily a Ruby programmer) to modify code. Also it's fragile with respect to nanoc changes.
Do you have any ideas?

Have the same problem. Option 1 seems the most obvious, but it requires the author to understand the intricacies of git - and I can see that going wrong easily.
I'd tend towards a modification of 2, where you have a custom gem based on nanoc but locking it to a specific version within the gemspec. A "course" would only have to contain a few basic elements, e.g.
/content
/output
Gemfile <== contains your "nanoc-course" gem
Gemfile.lock
Supply a template project for course authors and you'd only have to teach the authors how to use bundler.

Related

Laravel gettext or native localization? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I would like to ask what and why would be the preferred tool for localizing Laravel projects? I have already used a gettext plugin and it worked well. I like using POedit which allows translators using it without programming skills. Plus, the translation hints are cool, too.
Is there any good reason for using Laravel native localization? Or, are there any cons of using gettext?
Thanks!
Why not both: GetText and native localization?
Using GetText with source text is great for developers to work quickly and efficiently on new features without having to "make up" keys, switching files, maintaining consistency between keys and source text etc. Also, using GetText makes it easier to check if everything is translated and you don't need to worry if some keys/values are obsolete.
Using PHP trans() with keys/values is great for copywriting. It's easy for the marketing team or CEO to change the text for all languages (included the source language) without changing the code.
For these reasons, we created https://translation.io/laravel that allows you to use both syntaxes at the same time (and we suggest to only use PHP key/value when the source text needs to be editable through the translation interface).
The package is here is you need more technical info: https://github.com/translation/laravel
The native localization method is described in the Laravel documentation. You basically maintain language files for all languages you want to translate to. To pull them out of the file, you use trans(), trans_choice() (for plural) or __() helpers in Blade template.
Thats the most basic translation handling. At one level higher you might want save all translations to the database. There exists a few packages on Github which doing this. Like:
https://github.com/dimsav/laravel-translatable
https://github.com/barryvdh/laravel-translation-manager
and more. Just search for Laravel Translation.
This method only works as long as you use Blade for the frontend. If you use VueJs, Angular or React, the blade helpers won't work anymore and you have to find different ways how to handle this. This might depend on existent language handling of the aforementioned frontend framework.
I wrote an blog article about that topic.
#Peter Matisko, can you give us a little update on how did you decide, which one are you preferring to use?
Personally I tried quite a couple of different translation libraries, but gettext is still first choice for me:
extract all the translations from code and generate translation files (*.po)
translations editor that runs on Mac, Windows and Unix (Poedit initial release ~20 years ago)
translating plural forms

Questions about setting up a working Guard-RSpec example project

I'm trying to set up a working ruby project with guard-rspec.
I've mixed together the general method of a tutsplus tutorial with some new syntax as described in the RSpec videos and another post. The project can be found in the stack-overflow-question branch on github.
I'm also trying to practice namespacing as described in Programming Ruby 1.9. So eventually I'd like to have example.rb in my lib/example/ directory.
There's 4 questions I have about my project:
What do I need to put in my Guardfile to watch specific directories in my project for changes? I've several different ways which can be seen in my Guardfile as comments labelled like:
# Watch Specific Directory Attempt X
What is the difference between uncommenting lines 8 and 9 in my Guardfile (bellow Uncomment and set this to only include directories you want to watch) and adding "named group captures" like watch(%r{^lib/(?<path>.+)\.rb$}) { |m| "spec/lib/#{m[:path]}_spec.rb" } as described here
Where do I need to put the --clear option to make it persistent? I know I can run it with my binstub like bin/guard --clear and I've tried putting that in my Guardfile however it didn't work.
Are there any glaring convention, syntax, or clarity mistakes that you see in my project? I feel like I'm duck taping this whole thing together and I'd appreciate some guidance in piecing this thing together in a sensible way.
I'll answer the question in the title and cover the "sub-questions" as I go.
The best way to set up a project (as of now) is to use bundle exec guard --init rspec. This should give reasonable defaults to start work immediately. It's not perfect, but there is a lot of work planed to improve things, so do ask questions on GitHub instead (makes more sense).
Guard has to maintain backward compatibility, so there are some "non-intuitive" things for now and skimming through all the docs first (and wiki) is a good investment to quickly know what's available and where. Asking when confused or in doubt is also a good idea (one issue per question is best).
Guard uses a DSL to simplify setting up listeners. This is a bit non-intuitive and clunky at times, but it does help organize actions into groups, which can help maintain complex workflows. The DSL's command for e.g. clearing the terminal automatically is: (clearing: on). (This answers question 3).
There are all kinds of uses and scenarios, so Guard tries hard to make everyone happy and on every platform too. Guard uses Listen, which watches directories recursively (due to restrictions on OSX mostly). This usually isn't a problem, but for huge directions on OSX this can be very, very slow. That's why Guard lets you select which top directories to watch (like 'lib', 'app', etc.). Watching the whole project directory is very convenient, so that is still the default. More info on this is at the Listen project. So by default all directories (:directories statement) are "physically watched" (take up operating resources), though in Guard you only configure which changes you want to respond to (which is what watch statements do).
The words chosen are a bit misleading at times. E.g. watch in the DSL actually means: "out of all the changes happening, select changes matching ...". The block passed to watch is given the results of the match. That block should return a list of files for the current guard plugin to run. So "watch" probably is more misleading than helpful. "match" would probably be a better choice and it might replace "watch" in the future.
The guard-rspec project runs RSpec on changed files. You can see the exact RSpec commands if you run guard with the debugging option on, e.g. bundle exec guard -d. To simplify setup, Guard::RSpec uses a DSL that should work out-of-the-box if your project follows a given setup. E.g. dsl.watch_spec_files_for(ruby.lib_files) is defined here: so it pretty much already should do what you want if you put all your tested source files in lib. For other folders, you can add your own. E.g. Rails projects typically have sources also in an app directory, so in the default Guard::RSpec template there's an statement: dsl.watch_spec_files_for(rails.app_files) with the pattern defined as: rails.app_files = %r{^app/(.+)\.rb$} If you have a typical case that isn't covered, open an issue in that project. (covers question 2).
Everything looks fine in the example project and suggestions are mostly based on taste or preference. E.g.
Instead of let (:greeter) { Example::RSpecGreeter.new }, I'd use RSpec's implicit subject (but some may argue that it's less explicit and less readable)
if you're testing Example::RSpecGreeter, I'd recommend putting that class in a separate file and including it instead (require 'example/rspec_greeter')
you might add RubCop/Guard::RuboCop for detecting convention issues (covers 4th question)
you might want to check out Guard's own Guardfile used to test itself for a more "real-life" setup without the documentation clutter.
for best results I think it's best to copy a whole existing project and rename the parts you want to change. Usually there are many hours spent still fine-tuning things like alternate RSpec configs for Travis, special gem release tasks, certain workarounds and conveniences, etc.

Ruby Project VS Ruby Gem

I have read through Q&A/articles that explain the ideal structure of a Ruby project. I read the RubyGems guides on how to create a Ruby gem. I have just read a Q&A asking at what point a ruby project becomes a ruby gem but I can not for the life of me see the difference between the two. The structure seems to be the same. The files, where they go, everything looks the same to me. Is it how they're used? Can someone please explain the difference between the two to me?
The question that must be answered respect to 'Gemify' or not is: am I writing something that is readily reusable in a different context? If the answer is yes then your application is a candidate for 'Gemification'. If not then generally it is not worth the additional complexity to convert a Ruby project into a Gem.
For example. If one makes a CLI Ruby application that collects mortgage rates from multiple vendors and updates a database then there are two ways this could be converted into a gem.
First: You could generalise the interface/configuration and make it useful as a plugin/add-on/extension to projects written by someone needing the same or similar functionality. So someone could add the gemified version to their project and use it to do the grunt work for them and just make use of the results. This describes the most common use case for gems.
Second: However, you could also extract the framework of your CLI project layout into a generator gem for others to easily create their own CLI project layouts. This is how Rails came to be.

How to speed up Jekyll/Octopress generation?

I'm using Octopress as my blog engine. It's perfect. But if there are many posts, for example 400+ posts, the speed of generation is soooo slow.
So, is there any way to speed up Jekyll/Octopress generation?
Thanks.
Obviously if you are just working on one post, there is no need to wait for the entire site to generate. What you are looking for is the rake isolate[partial_post_name] task.
Using rake isolate, you can “isolate” only that post you are working on and move all the others to the source/_stash folder. The partial_post_name parameter is just some words in the file name for the post. For example, if I want to isolate the post from the earlier example, I would use
rake isolate[plain-english]
This will move all the other posts to source/_stash and only keep the 2011-09-29-just-type-the-title-of-the-post-here-in-plain-english.markdown post in source/_posts. You can also do this while you are running rake preview. It will just detect a massive change and only regenerate that one post from then on.
by #Pavan Podila
More Info: Tips for Speeding Up Octopress Site Generation
2013.01.08 update:
Hexo--A fast, simple & powerful blog framework, powered by Node.js.
Features:Incredibly fast - generate static files in a glance
2013.6.20 update:
gor -- A static websites and blog generator engine written in Go
gor has following awesome benefits: 1. Speed -- Less than 1 second when compiling all my near 200 blogs on wendal.net 2. Simple -- Only one single executable file generated after compiling, no other dependence
Install Ruby GSL
gem install gsl
You should notice a speed increase.
hexo powered by Node.js. I am using it, much faster than Octopress. And it provides a simple way to migrate your articles to hexo very easily.
You can generate only one post while you are writing it using
rake isolate[your-post]
and then
rake integrate
to go back to normal.
To fully answer your question, you can't generate only one post. You can see Octopress' Issue #395 on that subject, which explains that this is due to a limitation on Jekyll's side.
Reached this post with the same problem, but then did not quite like the idea of rake isolate. Also the inbuilt task does not integrate with the _drafts workflow.
So what I ended up using is to create a custom config.yml with the _posts folder excluded (using exclude) and have only the drafts folder built. You can pass in a different config file as command line parameter to jekyll. I just used this when actively writing new posts and while publish use the same old approach (which still does take some time). This approach builds only the draft post and I am good with that.
jekyll build --watch --drafts --config _previewconfig.yml
For those interested in the complete worklow take a look here
If your blog has a lot of images (and other static assets that do not change between builds), it is worthwhile to exclude them from Jekyll's build process, and instead manually update them as needed.
For whatever reason, Jekyll build is not intelligent when it comes to handling such assets. It will delete everything in the public folder, and re-copy the contents in source every time you build. This is wasteful if the assets haven't changed. This can be avoided by using a tool such as Robocopy (Windows) or Rsync (Linux) that is able to update only what has changed.
To tell Jekyll to ignore a folder, add the following to _config.yml:
exclude: # exclude from build
- folderPath
keep-files: # do not delete/empty copy in `public`
- folderPath
Then elsewhere, use whatever tool you want to update the folder.
For more things you can try, see this post.

Customize Gems or merge into main rails project

Currently I am writing a Ruby on Rails application, and I am using Gems, however sometimes I feel that Gems are not as flexible as I want them to be. To make them more flexible. Should I
Fork them on github, and customize it, but this still present the challenging of managing everything.
or
Strip and merge the code of the gem to the main application? This will allow further customization of the gem. This would be for situations where a Gem require another Gem's functionality.
or is there a better way of doing this?
Thanks
B
Choice A is the better answer for a number of reasons.
You get to merge in security updates, enhancements, and bug fixes easily.
Your changes may get merged into the core--in fact, consider if you could implement them in such a way as they live alongside the core functionality as options. If this happens, you have the ultimate win--nothing to maintain, and you can retire your fork.
Others can benefit from your changes.
Your project's footprint is kept smaller and focused by keeping the gem code isolated.
You'll have something to add to your Github "resume."
If its some kind if not so popular gem or "bicycle" from some previous studio or developer who started project(in my case).
I prefer deprecate this gem's and move code into project,
for example they have c***la-deploy - it's just wrapper to Capistrano 2 with own methods))) - I just delete it and rewrite on last Capistrano 3
Than that have own "CMS" c***la-cms where they wrap standard form_for or simple_form with name "twitter_form_for" ? - fist of all I start try to find gem who use this name, and than find in dependency gem's ...
Its take a lot of time for new developer involve in project - better move to standard rails methods/heplers
But anyway i understand for a what this studio do that - its just vendor lock and for client more hard to move out from them to another developers.
For example for startup its bad to use a lot of dependencies and if it's just simple website - dose not matter.

Resources