Skip to content

Latest commit

 

History

History
169 lines (129 loc) · 7.65 KB

README.md

File metadata and controls

169 lines (129 loc) · 7.65 KB

Ruby Videos

Codeship Status for andypike/ruby_videos Code Climate Test Coverage

A curated listing of quality videos about or related to the Ruby programming language.

This will help promote speakers, events and sponsors and will help Ruby programmers. I've been keeping a list of quality videos that I've watched and thought it might be a good idea to put it online and allow others to see the same create videos.

If you have a suggestion for a video, please suggest.

If one of your videos is listed on the site and there is something you do not like about it (description, bio, photo, etc) then please drop me a tweet @rubyvideos_ and I'll be happy to make the changes. Similarly, if you would like your video removed, just let me know.

Why?

This coding style is experimental

I wanted a simple project that I could experiment around with and try out some different things. There is also a Trailblazer version of this project that I started first. The reason for this project is that I liked many on the concepts in Trailblazer but also wondered if I could do something similar with just standard Rails and POROs (with a few lightweight gems).

Although this project is pretty simple, a lot of the code looks overkill for the project. That is expected at this stage. I wanted to experiment around with this style to see how it might turn out and having a real project is the best way to do that. I'm hoping to expand this project over time and see how easy it is to change with this architecture. I'm hoping that separating responsibilities will make change easy later.

Responsibilities

Based on the Trailblazer experiment and some other things I've been thinking and reading about, here are the general principles, structure responsibilities of the different areas of the project. These are ideas and plans before I start building the app. These may change over time.

Controllers

These are the entry point to our application. They deal with HTTP concerns such as reading the input, redirecting and rendering. They cannot contain business logic. To perform business logic they must call a Command (one per action if possible).

Models

Models derived from ActiveRecord::Base are only allowed to query the database. So these models should only contain the relationship bindings (belongs_to, has_many etc), scopes or class query methods. So AR models are only concerned with data access. AR models are the only classes that can call AR query methods such as #where etc.

Commands

A class that is responsible for the business logic of a single task in the system and should be named using verbs (Trailblazer calls these Operations). For example, PlaceOrder, RegisterUser or PublishArticle. These classes should have no knowledge of HTTP or how to query the database. If they require data they can only call AR-model query methods are defined in the model class not built in AR calls such as #where etc. The only exceptions to this are #find(id) or #find_by.

If a Command needs to update/insert then they can use the normal AR methods (#create, #save, update, etc).

Commands should be namespaced by concept. A concept may be a thing in the system such as User or something more abstract like Security. Concepts don't have to be mapped to your AR models but they can be.

Form Objects

These objects are responsible for dealing with data input from a user. They will be populated from the params hash and will validate it. I would like to keep these as close to simple POROs but I suspect I'll use a gem here which will make it easier to integrate with form builders such as simple_form.

The idea here is to remove the need to use strong_parameters as the form object will only use fields it's expecting for it's job. Also, this is an attempt to remove the need to use the ever confusing #accepts_nested_attributes_for by simplifying the forms so they only bind to a simple form object.

Mappers

The mappers will be responsible for taking the data held by a form object and mapping that data onto AR models for persistence (and back again). I may add some niceness for auto-mapping attributes with matching names etc, but we'll see how that goes.

Views

I would like to keep the views as simple as possible. Recently I've been using decorators (Draper gem) to add UI formatting to models. However, I'd like to try something different. I like the idea of having a presenter that takes a model(s) and is responsible manipulating the data for the view. This is more like the Cells gem which I may well use. So rather than a decorator per model we should have a presenter per view/partial. This presenter acts like a View Model.

Testing

In terms of testing there are few new things that I'd like to try out.

Page Objects

When testing with Capybara I'd like to start using Page Objects to encapsulate details of a page. For example, filling in forms and navigating to pages. This is an attempt to remove the details from the test and make them more focused on what you are trying to test. This makes things easier when coming back and reading the tests.

JS Tests

Testing javascript in a Rails app has been painful for me up to this point. Using Capybara with the :js tag really slows down the suite and are normally problematic. Simple things work ok, but more complex tests are hard to write and unreliable to run (especially in CI). So I'd like to try out some ways to improve this. I'd like to run up the app in a headless browser and then stub out the server side. I want to take a look at Teaspoon and investigate other solutions.

Mocking and fast tests

I normally try to avoid too much mocking if I can. But in an attempt to keep the tests fast I will still use factories to populate the database but only for Model query tests. As these are the only classes allowed to perform data access and will be tested, these calls can be mocked out for other tests. This should keep the tests fast but on the other hand, they will have implementation details (the mocks) inside them. Again, something to experiment with.

When is this style appropriate?

The structure above is not appropriate if you know you are only building a simple crud style app. This is overkill for that. However, a lot of apps start out simple and then increase in complexity over time. What I am trying to do here is to create a structure that consists of many small parts, each with their own single responsibility. As the app increases in complexity, this should provide a solid foundation for future change.

Contributing

If you would like to contribute, please create a feature branch and send in your pull requests.

Setup

git clone [email protected]:andypike/ruby_videos.git
cd ruby_videos
cp config/example.database.yml config/database.yml
cp example.env .env
  * Add your development details to .env
psql postgres
# create user ruby_videos with password '' CREATEDB;
# \q
bundle
rake db:create db:migrate db:seed
rake db:create db:migrate RAILS_ENV=test
rails s