Specific Ruby on Rails routes deliema - ruby-on-rails

Currently developing a RoR mobile web application for displaying information about particular places.
Let's call these places 'installations'. Each installation has at least one 'venue', which is a specific instance of the installation. So for example an installation could be a city park, and one of its corresponding venues could be the park during a concert or event. If this example is confusing, disregard, it doesn't matter much.
The data for these installations and their corresponding venues is hosted on Amazon Web Service S3 as json objects. I use HTTParty to read in the AWS S3 json objects. I am currently reading them in like so:
In the application controller I have:
inlcude HTTParty
base_uri 's3.amazonaws.com/our_bucket'
before_filter :set_up_httparty
def set_up_httparty
#installation = "INSTALLATION"
#venue = "VENUE"
#dir_url = "/#{#installation}/#{#venue}/"
end
In my corresponding controllers, where I get separate information I have:
response =
ApplicationController.get("#{#dir_url}/ConstantUniqueName.json")
Currently I am hardcoding INSTALLATION and VENUE values to point to a specific set of folders. This works great, but I need to be able to take in these values from the url like so:
www.themobilewebapp.com/INSTALLATION/VENUE/index
Now I am sure it is most likely possibly to pass in these values with params like so:
www.themobilewebapp.com/index?installtion=INSTALLATION&venue=VENUE
But if possible I would like to set my URL's up the previous way. I need to have the URL's be friendly for users to put in themselves and have QRC codes point directly to a specific installation and corresponding venue.
If not possible to be able to do something like www.mobwebapp.com/INSTALL/VEN/index then is it possible to set up sub domains for each venue and then pull in that venue as a string?
Any help is appreciated!! Thanks!

If you put this in your config/routes.rb file then you will be able to use the URL pattern that you want:
match ':installation/:venue/index', :controller => :venue, :action => :index

Related

Generating the URL of a nested resource without its parent (without using shallow)

In our application, many resources are nested under a common resource representing an organization. Most URLs include an organization ID the following pattern: /:organization_id/notifications/:id.
My problem is that I always have to give the current organization to generate the URL to any model. For example, the link to an existing notification would be link_to [#organization, #notification].
Since a notification already belongs to an organization, I was wondering if it was possible to generate my URL using link_to #notification and it would actually generate a URL including the organization ID of the notification. I was hoping that a configuration in the model would be able to achieve this but I could not find anything in the guides, the docs or the source code of Rails.
I would like to keep the organization ID visible in the URL as this is an information that is used by our customers. So I do not want to use shallow nested resources for this problem.
We are using Rails 5.2.0.
You want the resolve route definition method.
It is designed to do exactly what you want: configure a different behaviour when a single model instance is passed to url_for (as link_to does, for example).
Specifically, in your config/routes.rb, something like:
resolve("Notification") do |note|
[:notification_organization, note.organization, note]
end
It sounds like you were on the right track -- it's just a routing concern rather than a model one.

Rewrite dynamic URLs with multiple variables from ransack filter

I am building a little project in Ruby on Rails (which I am fairly new in using).
The idea ist to have a little listing website where users can filter all listings according to country and category.
I realized the filter using the gem ransack and it works.
Now, what I want to improve are the URLs after the user filtered the view, for example my URL looks like this:
domain.com/listings?utf8=%E2%9C%93&q%5Bcategory_eq%5D=sport&q%5Bcountry_eq%5D=Bosnia+and+Herzegovina
I would like to have pretty, clean URLs for SEO reasons. The above example would then translate to (or something in this direction):
domain.com/listings/all/c/sport/d/Bosnia-and-Herzegovina
I installed the gem rack rewrite and got some basic redirections working. But I can't figure out how the rule needs to be in order to achieve the URL above. Especially because the user could only use one filter which would result in a URL like this:
domain.com/listings/all/d/Bosnia-and-Herzegovina
Has somebody an idea or came across the same problem?
You should add something like this to your config/routes.rb:
get 'listings/all/c/:category/d/:country', to: 'listings#search'
# if you want URLs with only country or only category
# also add these two
get 'listings/all/d/:country', to: 'listings#search'
get 'listings/all/c/:category', to: 'listings#search'
Then in your ListingsController#search method (substitute for your actual controller and method name):
# Let's say user opens "domain.com/listings/all/c/sport/d/Bosnia-and-Herzegovina
def search
params[:category] # 'sport'
params[:country] # Bosnia-and-Herzegovina
# ... you code could use params above ...
end

Accessing URI params in the controller

(Learning RoR on my own, so pls forgive me if this is an obvious question)
I have an app to track books stored on shelves in libraries. A request should come in like:
GET books/library_id => shows all books on every shelf in a library
GET books/library_id/shelf_id => shows all books on one shelf in a library
GET books/library_id/shelf_id/book_id => shows a particular book
POST would use similar formats, except I will be using JSON in the POST body to supply the information (author, pub date, length, etc) for the book, shelf, or library
My question is, [:params] passed in to my controller seems to hold query (anything after a ?) and POST body parameters, but not the URL, which I need to parse and use to determine what to show. Is there a way to get this out of the parameters? I'm trying to avoid something like GET /books/?library_id/shelf_id
You can set up a route so that params will contain specific URL fragments in addition to the query string and/or post data.
In config/routes.rb:
get 'books/:library_id(/:shelf_id(/:book_id))', to: 'books#show'
In app/controllers/books_controller.rb:
class BooksController < ApplicationController
def show
library_id = params[:library_id]
shelf_id = params[:shelf_id] # may be nil
book_id = params[:book_id] # may be nil
# TODO: Do something with library_id, shelf_id (if present),
# book_id (if present).
end
end
Alternatively, if you wanted to process the URL with some very custom logic, you could have a wildcard route like get 'books/*sometext', to: 'books#show'. Then, in your controller action you could manually parse params[:sometext]. This would be considered "not the Rails way" but it's there if you need complete flexibility.
Finally, maybe it is worth mentioning that in your controller action you can get information about the request such as request.path, request.fullpath, request.url. But it doesn't sound like you need this in your case.

Changing urls in ruby on rails depending on different conditions

I'm new to ruby on rails....I wanted to know if there is a way to change the URL displayed depending on the client's response. I mean... here's an example:
I'm making a project showing listings in various places...
Now in general I have a home page, a search page, and a detail page for listings. So, respective URLs are officespace/home, officespace/search?conditions, officespace/detailpage?id=(controller-officespace)[&Conditions eg.---price,size,place,type...]
So, every time the client makes a request for search, the same URL is shown, of course with the given conditions.
Now I want that if the client asks for only the place and mentions nothing about size, price, etc., the url should be /listing/location_name.
If he mentions other conditions, then it'll be listing/(office_type)/size(x sq feet)_office_for_rent_in_locationname)
B.t.w. (I already have a controller named listings and its purpose is something else.)
And so on ........... Actually, I want to change URLs for a number of things. Anyway, please help me. And please don't refer me to the manuals. I've already read them and they didn't give any direct help.
This is an interesting routing challenge. Essentially, your goal is to create a special expression that will match the kinds of URL's you want to display in the user's browser. These expressions will be used in match formulas in config/routes.rb. Then, you'll need to make sure the form actions and links on relevant search pages link to those specialized URL's and NOT the default pages. Here's an example to get started:
routes.rb
match "/listing/:officeType/size/:squarefeet/office_for/:saleOrRent/in/:locationName" => "searches#index"
match "/listing/*locationName" => "searches#index"
resources :searches
Since you explicitly mentioned that your listings controller is for something else, I just named our new controller searches. Inside the code for the index method for this controller, you have to decide how you want to collect the relevant data to pass along to your view. Everything marked with a : in the match expressions above will be passed to the controller in the params hash as if it were an HTTP GET query string parameter. Thus we can do the following:
searches_controller.rb
def index
if params[:squarefeet] && params[:officeType] && params[:locationName]
#listings = Listing.where("squarefeet >= ?", params[:squarefeet].to_i).
where(:officeType => params[:officeType],
:locationName => params[:locationName])
elsif params[:locationName]
#listings = Listing.where(:locationName => params[:locationName])
else
#listings = Listing.all
end
end
And to send the user to one of those links:
views/searches/index.html.erb
<%= link_to "Click here for a great office!", "/listing/corporate/size/3200/office_for/rent/in/Dallas" %>
The above example would only work if your Listing model is set up exactly the same way as my arbitrary guess, but hopefully you can work from there to figure out what your code needs to look like. Note that I wasn't able to get the underscores in there. The routes only match segments separated by slashes as far as I can tell. Keep working on it and you may find a way past that.

Friendly URLs in Github

How has Github managed to get friendly URLs for representing repos of users? For a project called abc by username foo, how do they work around with a URL like: http://github.com/foo/abc. Are they fetching the abc model for the DB from the title in the URL (which sounds unreasonable as they are modifying the titles). How are they transferring the unique ID of the abc repo which they can fetch and show in the view?
The reason I ask is that I am facing a similar problem of creating friendlier URLs to view a resource. MongoDB's object IDs are quite long and make the URL look horrific. Is there a workaround? All the tutorials that demonstrate CRUD (or REST) URLs for a resource always include the object's unique ID(e.g. http://mysite.org/post/1 or http://mysite.org/post/1/edit. Is there a better way to do it?
Not having seen their code, I couldn't tell you exactly how they do it, but if you're using Rails there are at least two Ruby gems that will give you similar results:
Take a look at Slugged and friendly_id
http://github.com/foo/abc is a unique repository identifier (for that repo's master branch). I'd assume that somewhere they have a table that looks like:
repository-id | user-id | project-id
and are just looking up based on user and project rather than repository-id.
You'd need to do some domain-specific mapping between internal and user-friendly ids, but you'd need to make sure that was a 1:1 mapping.
See this rails cast on methods, gems and solutions to common problems you might get while modifying the application to use friendly urls.
http://railscasts.com/episodes/314-pretty-urls-with-friendlyid?view=asciicast
(although Ryan Bates deserves the rep+ for this)
I mocked a structure like this using FriendlyID and Nested Resources.
Essentially, use friendly ID to get the to_param-ish slugs in your routes, then set up nested resources. Using GitHub as an example:
routes.rb
resources :users do
resources :repositories
end
Then in your controller, say, for repositories, you can check the existence of params[:user_id] and use that to determine the user from the route. The reason I check for existence is because I did something like (roughly):
/myrepositories/:repository_id
/:user_id/:repository_id
So my controller does:
def show
#user = params[:user_id] ? User.find(params[:user_id]) : current_user
end
I followed this tutorial here to get started with this same project.
This is called URL rewriting if the web server does it (such as Apache), and routing when it happens in a web application framework (such as Ruby on Rails).
http://www.sinatrarb.com/intro#Routes
http://httpd.apache.org/docs/current/mod/mod_rewrite.html

Resources