开发者

most appropriate form to make re-usable Ruby on Rails code more re-usable?

I make a lot of rails applications, and there seems to be lots of way to make code reusable.

Among the things I reuse are the following:

css files, ini开发者_如何转开发tializers, views/shared/ partials admin images application helpers haml view templates gems etc...

I once tried to put all of this into a gem about a year ago and it backfired terribly mostly because of changing dependencies, and the fact that I was always tweaking the code and adding to it. This is not good as a gem, because to see a simple change take place you have to compile/publish/install the gem. So the gem is not right.

What are recommended ways to keep all of this "personal" code more or less modular so I can "plop" it into a new rails project and edit it as normal rails code (no gem compiling / publishing).

The two words that come to mind are engines and plugins, but I really don't know much about how either of them work. I've also heard of (confusingly) "templates", not the view kind.

What are your suggestions. I'd love to get this figured out!


You're on the right line of thinking with templates + engines.

Templates are great for one-time use. They allow you to generate an application that conforms to a specific, um, template, which provides an excellent base for you to build on top of. You can find more information about templates in this wonderful guide.

Engines, I think, are the better of the two. They allow you to provide that same base that templates would, but then also allow you to expand on that base for later. Within an engine you can have all the things you want. You can generate one of these fabulous creations by running this command:

rails plugin new pixelearth_base --mountable

This will generate the base of an engine, which then you can have all the things you wanted.

Let me show you the ways.

CSS files / images

CSS files go into app/assets, just like in a Rails 3.1 application, and are then processed the same way. You can read more about them in the Asset Pipeline guide. You can reference them exactly the same way you would reference them if they were inside your application. Of course, any asset inside your application named identically to one inside your engine will take precedence.

Initializers

These go in config/initializers, just like an application (hint: this is a running theme with engines). They work the same way and are explained in this section of the Configuring Guide, although I reckon you know that much already.

Shared views

These go into app/views/shared in your engine. Any file in your application named identically will take precedence over the file in the engine. The application will be able to seamlessly access any file in this directory, since engines have their view paths added to the application's.

Partials

Ditto.

Admin

Have you tried the wonderful rails_admin engine for this? Perhaps that would suit you. If not, you can build this functionality into your engine just as you would in an application.

Helpers

Work in much the same way as everything else. Add them to your engine and you'll be good to go. Although I am not confident in that last point, you may have to do helper SomeHelper at the top of the controller to get them included.

Haml

Specify this as a dependency of the engine in the engine's pixelearth_base.gemspec file using a line like this:

s.add_dependency 'haml', '3.1.3'

Your engine (and by extension, your application) would be able to use haml in views.

Templates

I am not sure what you mean by this, so I am going to gloss over it.

Gems

Shared gem dependencies should be specified in the pixelearth_base.gemspec just like the haml example.


Including the engine

Now, you're going to need to include this engine into your application but you don't want to go through the pain of updating a gem all the time. I reckon the best way to do this is to push the gem to GitHub and then specify a line like this inside your application's Gemfile:

gem 'pixelearth_base', :git => "git://github.com/pixelearth/pixelearth_base"

Whenever you update this gem and push new changes to GitHub, you will need to run bundle update pixelearth_base to update your application with the latest version. Each time you run bundle update it will be locked to that specific version. Any further changes to the engine won't be acknowledged until you run bundle update ... again.


Mounting the engine

One final thing which you asked about in IRC is mounting. If you happen to go the route of having shared functionality in your engine (i.e. controllers and so on) then you'll need to mount your engine within your application. This is very easy and can be done by putting this line in your config/routes.rb:

mount PixelEarth::Engine, :at => "pixelearth"

The PixelEarth::Engine class is defined in your engine at lib/pixel_earth/engine.rb and provides all the functionality it needs by inheriting from Rails::Engine. Any functionality from your application will now be available at /pixelearth in your application.


It depends on the file, if you want I can break an answer down for you. But my general advice is to keep your code small, lightweight and designed for one task. A good way of doing this is determining if the code you write is orthogonal. Wikipedia defines it in a computer science scope as this:

Orthogonality is a system design property facilitating feasibility and compactness of complex designs. Orthogonality guarantees that modifying the technical effect produced by a component of a system neither creates nor propagates side effects to other components of the system. The emergent behavior of a system consisting of components should be controlled strictly by formal definitions of its logic and not by side effects resulting from poor integration, i.e. non-orthogonal design of modules and interfaces. Orthogonality reduces testing and development time because it is easier to verify designs that neither cause side effects nor depend on them.

As far as constraining the size of your code you can leave that up to your own personal judgement on when and where you delegate methods and classes. However I like to keep in mind the separation of concerns and the single responsibility principle when working on breaking up the issues I face into smaller parts.

However you cant just write good code and leave it at that, you need to have a good way of distributing your code. I have a development server on my LAN that hosts many private Git repositories however you can use any VCS or DVCS to keep your code organized. I can then use this to keep my projects sourcing the latest versions of the files from the server when I need to update them and make changes and I can always branch if my requirements change for the project I'm working on. With Git I always have my code in version control so I use submodules to let me keep the latest version of the code handy and up to date.

Let me know if you want more information or if you dont use Git I can look for similar features on a VCS you are familiar with. Also I'd just like to note that this is a good question that has a lot of points and I'm glad you asked since I remember struggling with this and I'm sure others are tackling the same problem as well.


When I write sw for my app that I feel could be re-usable in other projects, I write it as its own plugin.

I copy the plugin dir model from one of the plugins that I'm already using.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜