Now that college is out for the summer and my classes have come to an end I need to be able to keep my mind sharp over the summer. I've decided to try my hand at making a nice enough ruby on rails app from start to finish.
I've tried doing this before but the problem I always run into is:
"I can't really finish this until that's done but it seems like it won't work unless I finish this other thing that need the first thing to work."
Basically my project gets out of hand really fast because I have no direction regarding what to work on and when.
My question to you, oh great and wise community of SO, is what is the most accepted way to go about developing a rails app.
Do I start with models, views, or controllers?
Is it better to make the HTML first or the server code?
What is the best way to get things done?
Thanks in advance!
The Rails community strongly promotes some form of test driven development. When you're just getting started, it probably doesn't make sense to start out writing tests, but you can still keep the same approach.
So, essentially you would just try to do what you want in the browser and write what you need as you need it to accomplish that.
So getting started, just generate a new rails app and start the server. It will give you the default Rails environment information. You don't want that to be the home page, so you go to the routes.rb file and define your root address (e.g. root 'welcome#index').
Now you reload the page you get the error "Uninitialized constant WelcomeController'. So now you need a controller. Add the controller.
Now you get an error 'The action 'index' could not be found for WelcomeController'. Define the index action on your WelcomeController.
Now you get the error 'Missing template welcome/index'. Add your views/welcome/index.html.erb view.
etc. etc.
Soon you'll find yourself needing models. Reference the model as you'd like to interact with it from the view. e.g. #articles.each do |article| etc.You'll get an 'undefined method on nil' or similar.
Then you define your model as you'd like to intereact with it in your controller (e.g. #articles = Article.all). Then you'll get an error that your model doesn't exist. Create the model.
Add the attributes to the model that you need in the view.
Repeat the process...
Design
Decide which features you are going to implement
Decide which gems you are going to use to implement those features
Configure and implement those gems/features in isolation - Use Git
Realize that you are spending a lot of time here.
Consider trimming the features or simplifying the design. Maybe go back to the top.
Start coding your master app - Use Git
Configure those gems together - Use Git
Write the Models - Use Git
Try to write controllers and views(Use scaffolding to get started, that way you'll be doing more hacking and less coding) - Use Git
Run into a problem in last three steps, or discover a new feature that you must implement to make everything work.
Solve that problem in isolation (in a separate rails app) - Definitely Use Git
Repeat
About Using Git
Damien Roche has suggested in the comments to use Git branches instead of testing new tools in isolation.
I have been using Git with Rails from the beginning, and I recommend using Git branches and testing new tools in isolation.
e.g.: You can see a public Github repository of mine here: https://github.com/spundun/emblem-coffee-emberjs-rails-starter-kit . It's a simple single branch repository where I document each step I'm taking to incrementally shape my project.
But when using a new tool or library, many times things will break, and you will start with no clue as to why things don't work the way they say it will, in the tutorial. Did I use the wrong version of the library? wrong version of Rails? Did I add tools in the wrong order?
To make sense of such problems, many times you'll want to compare a working directory that works with working directory that doesn't. Meaning you will want to have two working directories side-by-side.
Of course you can achieve the above by cloning one directory into the other and checking out two different branches, but we are getting ahead of ourselves. Before making a gem co-exist with a dozen other gems that you are using, you should make sure that you know how to get it to work in the simplest of the scenarios. Meaning with vanilla rails, with the bare minimum that is required.
So first you will make this isolated branch incorporating the new gem into a vanilla rails app. This branch is not related to your main branch in anyway, except it should use the same version of rails that you are using for your app. You can host it in the same repository or a separate repository, really doesn't matter.
Once you feel confident that you know how it's supposed to work in isolation, you can trace all the steps you took using the commit log of that isolated branch and incorporate those commits as appropriate in a feature branch on top of your master branch. And when you are done fixing bugs and making all the gems work in harmony, your feature branch is ready to be pulled into the master branch.
HTH.
I think it's a good question and I expect to see some insightful answers here.
In my opinion it's something that comes with practice, and you will constantly switch between M, V and C. I think the Model is usually the first part to implement, as it is often determined by the real world problem domain and therefore less fluid and subjective. Then the Controller and the View next. If you just implement the smallest working part with each iteration you get to see results sooner and it helps for not getting bogged down. (Although I like to try and define all fields in my model up front).
But really the best way to not get lost is step back and take pen and paper and sketch out the main workflow and entities in your system, in whatever notation works for you. Keep it simple so that you can visualise the main stuff your system does end to end, on just a page or two. Then when you're implementing, those designs can serve as a map for where you are in your build.
Of course you could also try to specify system tests up front (or rspec feature specs) to define what the system should do. This has never worked for me to be honest.
Many software development methodologies exist and continue to evolve albeit at a slower rate than the programming languages they implement. I'd recommend researching the Agile Manifesto and memorizing it's principles.
My typical Rails application workflow:
Write and implement a feature (Cucumber).
Write and implement a spec (RSpec).
Write a benchmark and refactor.
Related
How do I find what code is and isn't being run in production ?
The app is well-tested, but there's a lot of tests that test unused code. Hence they get coverage when running tests... I'd like to refactor and clean up this mess, it keeps wasting my time.
I have a lot of background jobs, this is why I'd like the production env to guide me. Running at heroku I can spin up dynos to compensate any performance impacts from the profiler.
Related question How can I find unused methods in a Ruby app? not helpful.
Bonus: metrics to show how often a line of code is run. Don't know why I want it, but I do! :)
Under normal circumstances the approach would be to use your test data for code coverage, but as you say you have parts of your code that are tested but are not used on the production app, you could do something slightly different.
Just for clarity first: Don't trust automatic tools. They will only show you results for things you actively test, nothing more.
With the disclaimer behind us, I propose you use a code coverage tool (like rcov or simplecov for Ruby 1.9) on your production app and measure the code paths that are actually used by your users. While these tools were originally designed for measuring test coverage, you could also use them for production coverage
Under the assumption that during the test time-frame all relevant code paths are visited, you can remove the rest. Unfortunately, this assumption will most probably not fully hold. So you will still have to apply your knowledge of the app and its inner workings when removing parts. This is even more important when removing declarative parts (like model references) as those are often not directly run but only used for configuring other parts of the system.
Another approach which could be combined with the above is to try to refactor your app into distinguished features that you can turn on and off. Then you can turn features that are suspected to be unused off and check if nobody complains :)
And as a final note: you won't find a magic tool to do your full analysis. That's because no tool can know whether a certain piece of code is used by actual users or not. The only thing that tools can do is create (more or less) static reachability graphs, telling you if your code is somehow called from a certain point. With a dynamic language like Ruby even this is rather hard to achieve, as static analysis doesn't bring much insight in the face of meta-programming or dynamic calls that are heavily used in a rails context. So some tools actually run your code or try to get insight from test coverage. But there is definitely no magic spell.
So given the high internal (mostly hidden) complexity of a rails application, you will not get around to do most of the analysis by hand. The best advice would probably be to try to modularize your app and turn off certain modules to test f they are not used. This can be supported by proper integration tests.
Checkout the coverband gem, it does what you exactly what are you searching.
Maybe you can try to use rails_best_practices to check unused methods and class.
Here it is in the github: https://github.com/railsbp/rails_best_practices .
Put 'gem "rails_best_practices" ' in your Gemfile and then run rails_best_practices . to generate configuration file
I had the same problem and after exploring some alternatives I realized that I have all the info available out of the box - log files. Our log format is as follows
Dec 18 03:10:41 ip-xx-xx-xx-xx appname-p[7776]: Processing by MyController#show as HTML
So I created a simple script to parse this info
zfgrep Processing production.log*.gz |awk '{print $8}' > ~/tmp/action
sort ~/tmp/action | uniq -c |sort -g -r > ~/tmp/histogram
Which produced results of how often an given controller#action was accessed.
4394886 MyController#index
3237203 MyController#show
1644765 MyController#edit
Next step is to compare it to the list of all controller#action pair in the app (using rake routes output or can do the same script for testing suite)
You got already the idea to mark suspicious methods as private (what will maybe break your application).
A small variation I did in the past: Add a small piece code to all suspicious methods to log it. In my case it was a user popup "You called a obsolete function - if you really need please contact the IT".
After one year we had a good overview what was really used (it was a business application and there where functions needed only once a year).
In your case you should only log the usage. Everything what is not logged after a reasonable period is unused.
I'm not very familiar with Ruby and RoR, but what I'd suggest some crazy guess:
add :after_filter method wich logs name of previous called method(grab it from call stack) to file
deploy this to production
wait for a while
remove all methods that are not in log.
p.s. probably solution with Alt+F7 in NetBeans or RubyMine is much better :)
Metaprogramming
Object#method_missing
override Object#method_missing. Inside, log the calling Class and method, asynchronously, to a data store. Then manually call the original method with the proper arguments, based on the arguments passed to method_missing.
Object tree
Then compare the data in the data store to the contents of the application's object tree.
disclaimer: This will surely require significant performance and resource consideration. Also, it will take a little tinkering to get that to work, but theoretically it should work. I'll leave it as an exercise to the original poster to implement it. ;)
Have you tried creating a test suite using something like sahi you could then record all your user journies using this and tie those tests to rcov or something similar.
You do have to ensure you have all user journies but after that you can look at what rcov spits out and at least start to prune out stuff that is obviously never covered.
This isn't a very proactive approach, but I've often used results gathered from New Relic to see if something I suspected as being unused had been called in production anytime in the past month or so. The apps I've used this on have been pretty small though, and its decently expensive for larger applications.
I've never used it myself, but this post about the laser gem seems to talk about solving your exact problem.
mark suspicious methods as private. If that does not break the code, check if the methods are used inside the class. then you can delete things
It is not the perfect solution, but for example in NetBeans you can find usages of the methods by right click on them (or press Alt+F7).
So if method is unused, you will see it.
I am currently working on a Rails 3 project that is divided up into four parts:
The public facing website
The administration website/backend
The models
The API for third party data access
As the models are shared between the three key components I want to keep them away from being in one main project, however each part needs access to the models, but I don't want to repeat the code and have different versions everywhere.
Currently I have the model code in a gem, and in each project's Gemfile I am referencing them with the following line:
gem "my_models", :path => "../my_models/"
However when I deploy to our test servers for my co-workers to evaluate the system on I need to pull the models from an external repository, so I swap out the above line with the following:
gem "my_models", :git => "git#private.repository.com:username/my_models.git"
This in its self works well, but its quite clunky in terms of 'versions' (i.e. I need to bump the version every time I wish to deploy the changes to the test servers), switch the line over to use git instead of local, and make sure that I'm pushing the files properly.
Previously I was using a shared git submodule, but this was just as awkward.
I would rather not build everything into one mega-project, as these tend to become monstrous and difficult to maintain, and I would also like to separate concerns if possible, so any changes I make to the administration site doesn't have much of a chance to impact the other components - obviously the models have the potential to cause issues, but that is a risk I have considered and understand.
What would people out there suggest when it comes to something like this? Or, am I going about it completely the wrong way?
Some additional background:
This app is a rewrite of an existing website which followed the model of 'lump everything into the one project' - unfortunately there are two issues here:
The app was badly developed - I inherited this project and when I first picked it up the load times were ~2 minutes per page with a single user - this has since been reduced but still has issues throughout
We are currently at our capacity limit of the current site and we anticipate that we will need to take on more load in the next 6 months - however scaling out with an 'all in one' app means we'll be wasting resources on scaling out the back end of the site which doesn't need it.
Essentially there are two things I want to separate - the Front end (being the public website and the API) and the back end - everything I know about software development tells me that combining all this together is not an ideal solution (and past history shows me that splitting these two is a good move in terms of ensuring front end performance).
Perhaps I need to look at this from another angle - keep the models in each project, and instead of sharing them between projects have a cut-down subset of functionality for each functional area (i.e. the backend needs to know who created a post, but the front end doesn't really care about that, so omit that logic when reading in the model).
drop the models project(put models into one of other parts, i'd suggest whatever you consider "more important"), put all projects into single repository(separate project folders) and make symlinks to models/libs/apis/whatever
your code is highly coupled together and you often need to make changes to few projects at once(like updating models and updating APIs that use them, etc)
one nice thing about single-repo-symlink setup is that your commits will be less fragmented and will usually represent full feature implementation - easier to track bugs, read history and maintain codebase
also when you deploy you don't need to read from many repositories - one less point of failure right there
release process is also simpler with such model as branch will now hold the scope of all projects
there are some drawbacks like symlinks dont work that well on windows and whatnot but for me it works perfectly
You can create a mountable engine that contains the shared models and create a gem out of it. This will handle the name spacing issues elegantly. Other nice aspect here is you get to share your assets also.
Watch this railscast for more details.
You'll still have to manage the 'versions' by pushing changes that need to be tested to a remote repo, but you can use the new local config of Bundler 1.2
http://gembundler.com/man/bundle-config.1.html#LOCAL-GIT-REPOS
This way it will pick up your local commits and you won't have to keep change your Gemfile upon deployment.
I know that this is not an solution for your particular problem. But I really suggest you to merge all projects into one. It is very usual to have all this parts in one application and there is no overhead. I think there is no not-awkward solution for this problem.
Take look at Git subtree.
This may work for you..
http://igor-alexandrov.github.io/blog/2013/03/28/using-git-subtree-to-share-code-between-rails-applications/
OR
You can write Rake task..
Example:-
namespace :sync do
desc 'Copy common models and tests from Master'
task :copy do
source_path = '/home/project/src-path'
dest_path = '/home/project/dest-path'
# Copy all models & tests
%x{cp #{source_path}/app/models/*.rb #{dest_path}/app/models/}
%x{cp #{source_path}/spec/models/*_spec.rb #{dest_path}/spec/models/}
# Database YML
%x{cp #{source_path}/config/database.yml #{dest_path}/config/database.yml}
end
See the below link.
http://hiltmon.com/blog/2013/10/14/rails-tricks-sharing-the-model/
Does your project have enough code coverage? If it does, I would try to separate the logic where it makes sense, and if a model is used in different projects, just pick one that fits best and write an API on top of that.
Then you could use that API to access those models (preferably using something like ActiveModel) on the other project. You would still have a simple CRUD, but all the core model logic would be handled externally.
Be sure to think well before splitting them up, though. You want to keep your domain tight on each app you create out of the Behemoth you want to torn apart.
Regarding engines:
I have used Engines for the same issue and it does help, but I also had to change my Gemfile to either point to a local path when developing, pushing the gem, then pulling it on the current project, which is the behavior you're not fond of.
I’m writing an application with Ruby on Rails. This application will be delivered to a minimum of two different customer types. The base is always the same but some of the views differ. That’s mostly it. For now.
Is there any way, for example using branches, to use the same code base and separate only the views, for example? I read the Git manual for branching but am still not sure if this is the best way to achieve what I need.
Another idea would be forking. But, is that clever? If I change something in the code of fork A, is it easy to merge these changes into fork B?
Branching and forking in git is not bad at all, as the merge support is great (possible the best of al VCMs).
Personally, I don't like the idea of branching or forking a project to provide different customization as it can very quickly become really difficult, e.g. what are you going to do if you have 15 different deployments?
I think a better approach is to build the application so it behaves differently depending on some parameters. I'm well aware that sometimes the implementations are very different, so this might not be useful anymore.
Another approach is to build the core of your app in a GEM which acts as a service to the application, and the only thing you customize per client are the views. Of course, the GEM should be generic enough to provide all the services you need.
Please share with us what you decided, as there's no best answer for your question.
It would probably be better to make you product select between the types at either build or runtime, that way you can use a single set of source.
Otherwise it is possible with branches, and merging, but you'll have more difficulty managing things. Forking is basically branching at this level.
I agree with #Augusto. You could run your app in 2 different environments, ie production_A and production_B. From there, you could use SettingsLogic to define configurations based on Rails.env, then reference those settings in your app when selecting which view to use for example.
I'm starting out with Ruby on Rails and I know of a few stuff already, but I was wondering if there was a "right" way of going about developing a project. Right now, I would create my models first using [script/generate model MyModel] then modifying them until I feel they are complete enough. Then I'd go for [script/generate scaffold MyModel] so I don't need to do as much coding for the views. Lastly I modify the views and add more models then scaffold some more for other features I might need.
Would there be a better way of doing this? Especially in the context of working with a team in developing a project? Thanks!
I'm sure everyone has their own workflow, but I think a typical one is this:
Specify the "domain" your project. This probably sounds silly, but before you get started you should really think about what exactly your website is going to offer. It doesn't need to be specific down to the last detail, but should have an idea so that you can perform the next step...
Design your database schema. I usually just plan this out on paper. There's a real art to creating a normalized database. Think of everything that needs to be "permanent" in your app, because it will have to be in the database and accounted for, with as little duplication as possible.
After this I usually do as you say: create my models (and migration scripts along the way). The main thing you want to get down in your models first is the associations with other models.
The next part depends on how comfortable you are as a developer in Rails. A lot of people enjoy the test driven development approach (TDD), and will write Unit tests (Rails provides excellent facilities for writing these, and rake tasks to run them). However, since you're just learning, you may want to write your tests after you implement your model business logic.
The road after this is pretty much up to you. You can work on your views/controllers/models as you need to. That's one of the beauties of Rails and agile development, you don't need a lot of boiler plate code to get started.
I'm probably weird in this, but I usually design my front page and get some basic CSS going, as I find I am more productive if my results are semi-nice looking.
I would probably avoid generating scaffolds though...I think you'll learn a lot more about the framework and spend less time removing unwanted code if you generate the individual pieces themselves.
In the context of developing with a team, things will probably be different. If you have a lot of complex business logic, some people may spend most of their time writing model code, while people more on the design side will be implementing view code. But you will have to meet in the middle of course, which will get easier as your project grows and becomes more modular. Just remember to use a version control system! Subversion if you want something easy to use and learn, Git if you're up for a challenge.
When you start working on an existing Rails project what are the steps that you take to understand the code? Where do you start? What do you use to get a high level view before drilling down into the controllers, models, helpers and views? Do you have any specific techniques, tricks or tools that help speed up the process?
Please don't respond with "Learn Rails & Ruby" (like one of the responses the last guy who asked this got - he also didn't get much response to his question so I thought I would ask again and prompt a bit more). I'm pretty comfortable with my own code. It's sorting other people's that does my head in and takes me a long time to grok.
Look at the models. If the app was written well, this should give you a picture of its domain model, which is where the interesting logic should live. I also look at the tests for the models.
The way that the controllers/views were implemented should be apparent just by using the Rails app and observing the URLs.
Unfortunately, there are many occasions where too much logic lives in controllers and even views. That means you'll have to take a look into those directories too. Doubley-unfortunate, tests for these layers tend to be much less clear.
First I use the app, noting the interesting controller and action names.
Then I start reading the code for these controllers, and for the relevant models when necessary. Views are usually less important.
Unlike a lot of the people so far, I actually don't think tests are the place to start. I think they're too narrow, too focused. It'd be like trying to understand basic physics/mechanics by first zooming into intra-molecular forces and quantum mechanics. I also think you're relying too much on well-written tests, and in my experience, a lot of people don't write sufficient tests or write poor tests (which don't give an accurate sense of what the code should actually do).
1) I think the first thing to do is to understand what the hell the app actually does. Use it, at least long enough to build an idea of what its main purpose is and what the different types of data might be and which actions you can perform, and most importantly, why.
2) You need to step back and see the big picture. I think the best way to do that is by starting with schema.rb. This tells you a few really important things:
What is the vocabulary/concepts of this project. What does "User" actually mean in this app? Why does the app have both "User" and "Account" models and how are they different/related?
You could learn what models there are by looking in app/models but this will actually tell you what data each model holds.
Thanks to *_id fields, you'll learn the associations between the models, which helps you understand how it all fits together.
I'd follow this up by looking at each model's *.rb file for (hopefully) comments, validations, associations, and any additional logic relevant to each. Keep an eye out for regular ol' Ruby classes that might live in lib/.
3) I, personally, would then take a brief glance at routes.rb as it will tell you two key things: a brief survey of all of the actions in the app, and, if the routes and controllers/actions are well named and thought out, a quick sense of where different functionality might live.
At this point you're probably ready to dig into a specific thing you need to learn. Find the controller for the feature you're most interested in and crack it open. Start reading through the relevant actions, see which models are involved, and now maybe start cracking open tests if you want to.
Don't forget to use the rest of your tools: Ruby/Rails debuggers, browser dev tools, logs, etc.
I would say take a look at the tests (or specs if the project uses RSpec) to get an idea at the high-level of what the application is supposed to do. Once you understand from the top level how the models/views/controllers are expected to behave, you can drill into the implementations.
If the Rails project is in a somewhat stable state than I have always been a big fan of using the debugger to help navigate the code base. I'll fire up the browser and begin interacting with the app then target some piece of functionality and set a breakpoint at the beginning of the associated function. With that in place I just study the parameters going into the function and the value being returned to get a better understanding of what's going on. Once you get comfortable you can modify the functionality a little bit to ensure you understand what's going on. Just performing some static analysis on the code can be cumbersome! Good luck!
I can think of two reasons to be looking at an existing app with which I have no previous involvement: I need to make a change or I want to understand one or more aspects because I'm considering using them as input to changes I'm considering making to another app. I include reading-for-education/enlightenment in that second case.
A real benefit of the MVC pattern in particular, and many web apps in general is that they are fairly easily split into request/response pairs, which can to some extent be comprehended in isolation. So you can start with a single interaction and grow your understanding out from that.
When needing to modify or extend existing code, I should have a good idea of what the first change will be - if not then I probably shouldn't be fooling with the code yet! In a Rails app, the change is most likely to involve view, model or a combination of both and I should be able to identify the relevant items fairly quickly. If there are tests, I check that they run, then attempt to write a test that exposes the missing functionality and away we go. If there are no tests then it's a bit trickier - I'm going to worry that I might inadvertently break something: I'd consider adding tests to give myself a more confidence, which will in turn start to build some understanding of the area under study. I should fairly quickly be able to get into a red-green-refactor loop, picking up speed as I learn my way around.
Run the tests. :-)
If you're lucky it'll have been built on RSpec, and that'll describe the behavior regardless of the implementation.
I run rake test in a terminal
If the environment does not load, I take a look at the stack trace to figure out what's going on, and then I fix it so that the environment loads and run the tests again
I boot the server and open the app in a browser. Clicking around.
Start working with the tasks at hand.
If the code rocks, I'm happy. If the code sucks, I hurt it for fun and profit.
Aside from the already posted tips of running specs, and decomposing the MVC, I also like:
rake routes
as another way to get a high-level view of all the routes into the app
./script/console
The rails irb console is still my favorite way to inspect models and model methods. Grab a few records and work with them in irb. I know it helps me during development and test.
Look at the documentation, there is pretty good documentation on some projects.
It's a little bit hard to understand other's code, but try it...Read the code ;-)