Mixing backbone.js routers and rails controllers - ruby-on-rails

I'm currently attempting to wrap my head around grafting backbone.js into my rails application. For starters, I want to build it into a a specific part of the rails application at /applications. With that said I have a rails resource "resources :applications" which gives me localhost:3000/applications. Now when I instantiate backbone for /applications I get anchor tags for the backbone routing at that rails resource. IE localhost:3000/applications/#applications/5.
Given that I'm only going to be using backbone at specific parts of the rails app, thus not making it a single page app, is this the right way to do things? The URL appears to be a bit redundant.
The correct answer might be that I need to do away with the backbone router? If so, then how can :id be passed to the backbone application when attempting to look up a collection / model.
The point of me using backbone is to help organize a particular section of the rails app that will be javascript heavy.
I should mention that I can change the router to something like:
routes:
'': 'index'
':id': 'show'
which will give me the url of localhost:3000/applications/#/1 - however I think this paints me into a corner and will not allow me to use backbone on other rails resources. If I were to have localhost:3000/dashboard with backbone invoked then the wrong backbone.js functionality would get executed.
Another thought would be to have an invocation of a backbone router per rails resource. I could use the aforementioned routes code since the router would only be invoked for that rails resource.

I ended up figuring this out. I switched to using backbone-rails and followed their tutorial in getting a sample application up and running; https://github.com/codebrew/backbone-rails. The solution came in the rails html.erb and only loading the specific router that I needed for the rails resource.
routes:
"new" : "newPost"
"index" : "index"
":id/edit" : "edit"
":id" : "show"
".*" : "index"
Then in say a posts.html.erb I could put the following.
<div id="posts"></div>
<script type="text/javascript">
$(function() {
// Blog is the app name
window.router = new Testing.Routers.PostsRouter({posts: <%= #posts.to_json.html_safe -%>});
Backbone.history.start();
});
</script>
If my answer doesnt make sense, I suggest going through the tutorial on the github link that was aforementioned.

Related

Vue.js router with Ruby on Rails routes

I'm currently working on a application with a Ruby on Rails backend and Vue.js frontend. It's a single page application. I'm using the webpacker gem to build my main JS file.
I've added vue-router and and a couple frontend routes. I'm able to navigate using <router-link> which correctly renders the appropriate component. What I can't figure out is how do I setup my frontend routes so that someone can directly navigate to a URL without hitting my Rails routes.
For example if I type /sample-route I'd like to hit my Vue.js route and not my Rails route. I still want to be able to make API calls to my Rails routes as well. For example /api/users.
My problem was solved by adding <router-view></router-vew> into my main Vue.js component.
Here's my rails routes file as well:
Rails.application.routes.draw do
namespace :api do
# api routes here
end
root 'application#index'
get '/*path', to: 'application#index'
end
Depending on how many routes you have, you can add your Vue routes to routes.rb and send them to your root Vue application route. e.g. Webpacker is rendering your js pack with controller#action vue_controller#app. Your Vue app router uses /user/profile. In routes.rb, add a route:
get "/user/profile" => "vue_controller#app" # <- The controller action rendering your Vue pack
If it seems unmaintainable to redefine every Vue route in routes.rb, you may want to look into a universal fallback route that sends them to the vue app controller action. As long as you don't change the route, but just respond with the Vue controller action, the Vue router will take care of rendering the right components for that route when the page loads.
In Rails 4, you can use something like the answers in this SO question to help you out with setting up a "catch-all" route Rails catch-all route.
EDIT: Using a catch all route does lead to some problems with 404's. If the user requests a route that doesn't exist, the Rails app will still send them the Vue pack. To fix this, you would need to add some unknown route handling in your Vue router to render something like a 404 page.
There is one more approach which will be useful and handles sub-routes as well (having separate vue apps per page in a single rails app):
routes.rb
Rails.application.routes.draw do
# this route entry will take care of forwarding all the page/* urls to the index
get 'page_controller/*path', to: 'page_controller#index', format: false
end
Additionally, please handle the api and index routes separately based on the design.
vue-routes.js
const router = new VueRouter({
mode: 'history',
base: '/page_url',
routes: [
...
]
});

Does Backbone.js have something like 'rake routes' from Ruby on Rails?

Is there an easy way to see all the routes my Backbone.js application has built while it's running?
Ruby on Rails has rake routes, which shows things like this:
unicorns GET /unicorns(.:format) unicorns#index
POST /unicorns(.:format) unicorns#create
new_unicorn GET /unicorns/new(.:format) unicorns#new
edit_unicorn GET /unicorns/:id/edit(.:format) unicorns#edit
unicorn GET /unicorns/:id(.:format) unicorns#show
PUT /unicorns/:id(.:format) unicorns#update
DELETE /unicorns/:id(.:format) unicorns#destroy
Does Backbone have an equivalent?
You can always check a router prototype/instance routes property to get all statically declared routes. So if you're not generating them programmatically, you'll get the cleanest output as so:
console.log( router.routes );
If you're using this.route() to dynamically add routes, then you should check on the Backbone.History object, this will be the complete list of routes used inside your app; although the output is a little bit messiers (routes are compiled to regexp, etc).
console.log( Backbone.history.handlers );
Note that this property ain't documented, so there's no garantee it will be kept in future version of Backbone. I'd only use it for debugging purpose.

Using Ruby on Rails link_to to link to controller action

I'd just started toying around with Ruby on Rails and had come across an issue with linking to another action in a controller from a particular view. I am almost certain it's an issue (or lack of code) in my routes.rb file, but I think I'm misunderstanding exactly how this file works & what I have to do. I've got a solution but pretty sure it's not the "best way" to do it.
I have one controller called home with two actions, index (which is the default) and newbill. Inside index.html.erb I have:
<h1>Home View</h1>
<%= link_to "new", :controller => "home", :action => "newbill" %>
However I was getting a routing error:
No route matches {:controller=>"home", :action=>"newbill"}
Doing rake routes gives me the following:
root / {:controller=>"home", :action=>"index"}
I then (following some Googling) added this code to routes.rb
match 'home/newbill' => 'home#newbill', :as => :newbill
And then in my index.html.erb I've got this:
<%= link_to "Name", newbill_path %>
And now this works as expected. My questions however are:
Why does this work? What exactly is going on behind the scenes?
Surely this is not the best way to do it? Adding another match 'home/newbill'... for every controller / action I want to link to seems a rubbish way of doing things.
I really like Ruby, but struggling a bit with this aspect of Rails...routing in general is messing up my head a bit I think!
Any help is much appreciated :D
Thanks,
Jack
I guess the first time your code didn't work because your home controller is defined as a resource.
If you define a controller as a resource in routes.rb file it will support only 7 standard methods (according to REST architecture):
index
new
create
show
edit
update
destroy
If you need any more custom routes you should add them manually, say in your case 'newbill', may go as:
resources :home do
collection do
get :newbill
end
end
But as per my understanding, your newbill method should go to bills controllers new, method not in the home controller.
You are right, Rails routes are little bit confusing (at least for me), but once you understand you can do lots of cool stuff.
Read here for the Rails official routes documentation:
http://guides.rubyonrails.org/routing.html.
You should check out the Rails Routing guide. A read through will help you understand what is going on behind the scenes.
This works becuase rails filters every request through the router looking for a match. This enables you to define custom routes such as domain.com/post when the path is actually blog#post. Prior to rails 3, a catch-all route was the last route in the routes file. This allowed you to define a controller and action and it would just work. I'm on my iPad and not near any projects, so I can't verify it, but I think that route is still there in rails 3.1, it just needs to be umcommented.

Generating an object's absolute url without html markup

Is there a method like "full_url" such that #comment.full_url or full_url_for(#comment) returns "http://www.host.com/comments/id" where www.host.com is the default host domain and id is #comment.id. Or, if not, what would be an elegant way to generate this url string?
I'm pretty new at Rails, most of the methods I've learned insert the tag and other markup.
url_for is not helping because I can't do something like the following:
url_for(#comment, {:only_path => false})
I've spent way too much time trying to figure this out. It came down to either hacking or asking for the right way on SO. Here I am.
If you are setting up your routes correctly in your config/routes.rb file then you should have access to named routes in your controller and in your views. Which should mean that all you should need to do is:
comment_path(#comment)
Or for the full url
comment_url(#comment)
To see a list of all of the routes from the command line, you can type rake routes from the project root. Welcome to rails! Here is a good resource for rails 3 routing: http://guides.rubyonrails.org/routing.html
some additional resources via Railscasts:
http://railscasts.com/episodes/231-routing-walkthrough
http://railscasts.com/episodes/232-routing-walkthrough-part-2

Blank page when navigating to http://localhost:3000/say/hello

I'm new to Ruby on Rails and am doing my first tutorial and am running the latest version of rails 3 and ruby 1.9.2. After creating my controller and navigating to http://localhost:3000/say/hello I'm receiving a blank page. I do see the Welcome to Rails message when I just go to http://localhost:3000. I've done some Google searches and people have similar problems but there is no clear fix. I've never really worked with MVC before so the concept of routing is fairly new to me.
Below is my controller:
class SayController < ApplicationController
def hello
end
def goodbye
end
end
My view:
<h1>Say hello to Rails!</h1>
You should delete the public/index.html file as that will mess with your routing and display by default. Have you set up your routes already, and what is the exact location and filename of the template?
You will need something like in your config/routes.rb file to correctly route that url to your template/view:
match '/say/hello' => 'say#hello'
First delete the index.html file from your public folder. Then, go to the app/views and check the views for the say controller. You should have a hello.html.erb.
The answer to your particular question was answered already by Bitterzoet, but I thought you might want some alternative learning resources.
I'm not sure which tutorial you're starting with, but I find it odd that they're not using RESTful routes. You can find out what routes you have set up at the moment by going to the console and typing "rake routes". If you would like a different tutorial, I recommend the one here:
http://www.wiki.devchix.com/index.php?title=Rails_3_Curriculum
I'd also recommend http://railsforzombies.org/ as a good first-time rails experience.
A fun general line to add to config/routes is:
match ':controller(/:action(/:id(.:format)))'
While developing, this will allow you to display the controller/action in address bar for ALL controller/action/id.format etc.
Like Bitterzote wrote, if controller is "say" and action is "hello", http://localhost:3000/say/hello .
If you use controller "say" and action "move", http://localhost:3000/say/move .
I've found this route to be very useful during development, but change this if you launch your application! (Rails warns: "Note: This route will make all actions in every controller accessible via GET requests.")

Resources