Rails URL and Path Helpers in Engines Like Spree - ruby-on-rails

I'm trying to use some URL and/or path helpers in my Rails 4 Engine views such as resource_url or resource_path. These engines are configured a bit differently than the typical --mountable tutorial out there. In fact, they more closely resemble how Spree does it, without the Spree::ENGINE_NAME namespace.
Like Spree's architecture, I'm attempting to create core engine that my other engines depend on. For example, my backend engine's routes.rb file looks like this:
Core::Engine.add_routes do
# Check to see if the request comes in on a subdomain
# The Subdomains class passed into constraints()
# is a class defined in lib/subdomain.rb
constraints(Subdomain) do
match '/manage' => "manage#index", :via => [:get]
end
end
In a view inside my backend engine, I'd like to be able to use some URL/path helpers to do something like this:
<%= link_to manage_path, manage_path %>
This doesn't work, because I'm drawing the routes on the core engine. So, I must use
<%= link_to core_engine.manage_path, core_engine.manage_path %>
Spree somehow gets around this, but I'm not sure how. For example, in backend/app/views/spree/admin/products/index.html.erb:
<%= link_to product.try(:name), edit_admin_product_path(product) %>
Notice, the edit_admin_product_path, but no mention of this actually being drawn on the core engine.
Any ideas?

We get around this by drawing all the routes on the core engine using add_routes which exists for reasons I won't go into here because it's a long tangent. Necessary evil for this kind of work, though.
The isolate_namespace method within Core::Engine scopes everything to the spree namespace. If you're inside a controller that's been drawn underneath the Spree::Core::Engine routes and you want to reference a route for another controller also drawn under that route then you can leave off the spree. prefix on the routing helper.
If you're routing to a different engine, then you will need to have the prefix: main_app. or whatever.
The Engines Guide explains this in greater detail, and I'd recommend reading that.

Related

Rails path helpers without routes

We are in the process of taking a few pages out of our rails app to be served separately (they are a few static pages with some content being managed through a cms). The urls will stay the same. Our own routing system in front of the servers will decide which request should go to the rails app and which to the static part.
My question is about path helpers that we use quite a bit throughout the rails app, such as link_to about_path that generate mahwebsite.com/about. As I understand I can just leave them be, they will still generate correct urls. My only concern is that for them to work I'll have to keep the routings in the routes file, which will have to be connected to the dummy controller methods. Seems like a lot of redundant code just to fool rails into creating path helpers.
Alternatively, I can hard-code links to the static pages. But before I start replacing a whole lot of code, I'd like to know if there is a clean Railsy way to keep the path helpers without having to route to the redundant controllers.
Thanks.
Why not just create your own helper method? E.G.
# application_controller.rb
def about_path
"mahwebsite.com/about"
end
helper_method :about_path
alias_method :about_url, :about_path
This will overwrite any Rails helper method and do exactly what you're after :)
Hope this helps - give me a shout if you've any questions or comments.
How about
resources :custom_pages, only: [:your_options] do
get :view/:page_id_or_whatever_for_identify
end
and do the following content with the controller?

What's the "Rails Way" to create route helpers to other hosts?

My app consists of two rails servers with mostly different concerns sitting behind a reverse proxy. Let's call them Server1 and Server2. Occasionally, Server1 needs to render a link to a url on Server2. Is there a good way to use Rails route helpers for this? Specifically in Rails 2? I came up with this:
ActionController::Routing::Routes.draw do |map|
# other routes omitted
map.with_options(:host => 'server2.example.com') do |add|
# create a named route for 'http://server2.example.com/thingies'
add.server2_thingies '/thingies', :controller => 'fake'
# create a named route for 'http://server2.example.com/thingies/combobulate'
add.enhance_server2_thingies '/thingies/combobulate', :controller => 'fake'
# create a named route for 'http://server2.example.com/mabobs/combobulate'
add.enhance_server2_mabobs '/mabobs/combobulate', :controller => 'fake'
# etc..
end
end
So then I can use server2_thingies_url and such in my views. This works, but it makes me feel like a bad person because there is no FakeController and I certainly have no intention of routing requests to it. I considered making helper methods and placing them in app/controllers/application_controller.rb, but a colleague made the argument that it is best to keep all route helpers in routes.rb, so things like rake routes will be accurate, for instance. Is there a better way?
I think I'd make a counter-argument to your colleague: if you're having to dirty up routes.rb with a "FakeController", then your rake routes is still not going to be accurate. In fact, I'd say that this is exactly the kind of thing that a helper was meant to help: it's taking logic that belongs purely in the view (link generation), and removing it from your view templates. Helpers are also easier to maintain and tweak.
Another advantage to the helper style is that if and when it's time to upgrade to Rails 3.x, the less hackish your routes.rb file is, the happier you will be - and that I can attest to from experience. :)
I'd just pass in :host to your foo_path or foo_url calls.
Seems cleaner than messing around with a FakeController

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.

Take existing project and move it into a Ruby on Rails environment

I have the front end of a website built. It is made from a number of HTML, JavaScript, and Jquery files. Is there a way to take those files and move them into a Ruby on Rails environment so that I don't need to remake everything?
Sure. Create a new rails app (rails new app-name). Copy your existing javascript files into the Rails project at public/javascripts/. Your views/html are a bit more dependent on how you want to grow.
One option is to create a single PagesController and not bother with resources/models/etc, and you would just put all of your "views" into /app/views/pages/. You don't even have to rename them to .html.erb like you would conventionally see — you can leave them as just plain html. Your routes.rb file would look something like this:
get '/:action', :controller => 'pages', :as => 'page'
Which would afford you routes like "example.com/hello_world" that would route to PagesController#hello_world, rendering "app/views/pages/hello_world.html". If you want to use ERb, you can add that ".erb" suffix to your view file and then you can use the page_path helper to assemble links:
<%= link_to 'Hello World Demo', page_path('hello_world') %>
You will still probably want to extract the common elements into a layout at app/views/layouts/application.html.erb (again, the ERb being optional).
Another route would be to actually separate your application into resources. If you have a page that lists books, for example, you could create a BooksController and put the relevant view under app/views/books/index.html. This doesn't make sense to do if you're not going to provide some additional functionality in the future, though.

New to Rails. Doubt in Big URL Routing

I have just started learning ruby on rails. I have a doubt wrt routing.
Default Routing in Rails is :controller/:action/:id
It works really fine for the example lets say example.com/publisher/author/book_name
Could you tell me how do you work with something very big like this site
http://www.telegraph.co.uk/sport/football/leagues/premierleague/chelsea/
Could you let me understand about the various controllers, actions, ids for the above mentioned url and how to code controller, models so as to achieve this.
Could you suggest me some good tutorials when dealing with this big urls.
Looking forward for your help
Thanks in advance
Gautam
This is achieved using nested resources (read or google for "rails restful routes". In your case it could look something like this:
map.resources :sports do |sport|
sport.resources :leagues do |league|
league.resources :team
# probably more nested routes for members or sponsors or whatever...
end
end
end
You can also view your defined routes with rake task:
$ rake routes
This RailsCasts episode also covers some basics on restful routing with nested resources.
The routing engine can handle URLs of arbitrary size. It all depends on what your spec is. For that it would be:
map.sport_league_team '/sport/:sport/leagues/:league/:team'
What controller you route that to is the important part. This is then called like:
<%= link_to("Chelsea", sport_league_team_path('football', 'premierleague', 'chelsea') %>
You can always examine what routes are defined with:
rake routes
The Rails Routing from the Outside In guide is a good place to start.

Resources