Change default url from Active Storage - ruby-on-rails

Can we change the default 'permanent' url create from active storage to redirect to S3. Is something like rails/active_storage/representations/. I don't like the framework name in the url.
Thanks

UPDATE:
Recently, there was an addition which makes the route prefix configurable in Rails 6: https://guides.rubyonrails.org/6_0_release_notes.html#active-storage-notable-changes
It's just a matter of configuration:
Rails.application.configure do
config.active_storage.routes_prefix = '/whereever'
end
Unfortunately, the url is defined in ActiveStorage routes.rb without easy means to change:
get "/rails/active_storage/blobs/:signed_id/*filename" =>
"active_storage/blobs#show", as: :rails_service_blob
get "/rails/active_storage/representations/:signed_blob_id/:variation_key/*filename" =>
"active_storage/representations#show", as: :rails_blob_representation
One solution starting point I can think of is defining your own Routes in addition and overriding the "rails_blob_representation_path" or similar
get "/my_uploads/:signed_blob_id/:variation_key/*filename" =>
"active_storage/representations#show", as: :my_upload
and then overriding the path in a helper file and include the helper into the Named Helpers:
How to override routes path helper in rails?
module CustomUrlHelper
def rails_blob_representation(*args)
my_upload(*args)
end
end
# initializer etc.
Rails.application.routes.named_routes.url_helpers_module.send(:include, CustomUrlHelper)
The solution might need some adjustments though, I didn't tested it.

Related

change routing name dynamically

I have to modify the routes file in order to have SEO improvement.
This is my context, a rails backend generate a JSON feed with the route's name in, I have to read it and change the default name.
For example, I have this:
get '/people' => 'people#show', as: :people
and I'd like to change /people in some value read from my JSON feed.
I created a class to get the JSON object in my app
class JSONDatabase
def initialize(kind_of_site)
#kind_of_site = kind_of_site
end
def fetch_database_remote(url)
JSON.parse(open(url).read)
end
end
but how can i access it in routes file?
Thank you
You don't necessarily need to modify your application's routes. What you can do is define a wild card route that leads to a unique controller where you read the updated route. This approach is kind of hackish but gives you the unlimited routes you need without modifying the routes.
Your config/routes.rb file would look something like this:
resources :defined_models
root to: 'controller#action'
# At last we define the wildcard route
get '/:route' => 'routing_controller#routing_action'
Then, at this routing action we can do the job of seeing if this route (now defined in the params[:route] variable) corresponds to the modified one. Just remember to redirect to a 404 if the route given is not defined, since with this approach you loose the Rails default way of dealing with undefined routes.

Can the object passed into a Rails route change the hostname?

I want:
channel_url(channel_object) # http://domain1.com/something/here
channel_url(other_channel_object) # http://domain2.com/something/here
Basically, the object passed into channel_url should be able to change the hostname.
I could do this by defining a helper method called channel_url, but I'd much rather use the generated rails routes methods.
This cannot be done with routing out of the box. Routes are made to deal with routes within the application. Even subdomains are not really part of it.
You could alter the url_to method from ActionView::Helpers::UrlHelper to look at the object passed into it.
def url_for(options={})
if options.respond_to? :domain
super options, domain: options.domain
else
super
end
end
Something like that, given that your channel_object responds to domain. :)
Hope this helps.

how to create dynamic routes and helpers in rails3

i have a task to create mapping of different urls at run time .
In the application i have a GUI interface which displays list of routes from routes.rb file.
User has the ability to change that url to some different name from the interface
eg. (abc/mno) --user can change them to --(hello)
so if user type /hello in the browser request is redirected to /abc/mno
i have to store those mapped routes in a database.
how to add a dynamic mapped route to already defined routes(routes.rb) while creating a new record in database
how to add routes from the database while loading routes.rb file.
i am not able to figure out how to extend the default router so that it can include routes from the database ..
I don't have a complete solution for you, but you can start with two approaches:
Use custom URL constraint: Dynamic URL -> Controller mapping for routes in Rails
Use Rack middleware: Dynamic Rails routing based on database
If you don't want to use rack middleware, you can use constraints. Hopefully, your dynamic routes are scoped to something, like "/abc/anything-after-here-can-be-dynamic", as opposed to straight off the root...
So, lets say you wanted dynamic routes based upon User's first name, then you would do the following:
#config/routes.rb
match '/abc/:route' => "abc#dynamicroute", :contraints => DynamicRouteConstraint.new
#lib/dynamic_route_constraint.rb
class DynamicRouteConstraint < Struct.new
def matches?(request)
User.find_by_first_name(request.params[:route]).present?
end
end
#app/controllers/abc_controller.rb
class AbcController < ApplicationController
def dynamicroute
#user = User.find_by_first_name(params[:route])
#render or redirect, however you wish
end
end

Remove Routes Specified in a Gem?

Is there a way to remove routes specified in a gem in Rails 3? The exception logger gem specifies routes which I don't want. I need to specify constraints on the routes like so:
scope :constraints => {:subdomain => 'secure', :protocol => 'https'} do
collection do
post :query
post :destroy_all
get :feed
end
end
Based on the Rails Engine docs, I thought I could create a monkey patch and add a routes file with no routes specified to the paths["config/routes"].paths Array but the file doesn't get added to ExceptionLogger::Engine.paths["config/routes"].paths
File: config/initializers/exception_logger_hacks.rb
ExceptionLogger::Engine.paths["config/routes"].paths.unshift(File.expand_path(File.join(File.dirname(__FILE__), "exception_logger_routes.rb")))
Am I way off base here? Maybe there is a better way of doing this?
It is possible to prevent Rails from loading the routes of a specific gem, this way none of the gem routes are added, so you will have to add the ones you want manually:
Add an initializer in application.rb like this:
class Application < Rails::Application
...
initializer "myinitializer", :after => "add_routing_paths" do |app|
app.routes_reloader.paths.delete_if{ |path| path.include?("NAME_OF_GEM_GOES_HERE") }
end
Here's one way that's worked for me.
It doesn't "remove" routes but lets you take control of where they match. You probably want every route requested to match something, even if it is a catch all 404 at the bottom.
Your application routes (MyApp/config/routes.rb) will be loaded first (unless you've modified the default load process). And routes matched first will take precedence.
So you could redefine the routes you want to block explicitely, or block them with a catch all route at the bottom of YourApp/config/routes.rb file.
Named routes, unfortunately, seem to follow ruby's "last definition wins" rule. So if the routes are named and your app or the engine uses those names, you need to define the routes both first (so yours match first), and last (so named routes point as you intended, not as the engine defines.)
To redefine the engine's routes after the engine adds them, create a file called something like
# config/named_routes_overrides.rb
Rails.application.routes.draw do
# put your named routes here, which you also included in config/routes.rb
end
# config/application.rb
class Application < Rails::Application
# ...
initializer 'add named route overrides' do |app|
app.routes_reloader.paths << File.expand_path('../named_routes_overrides.rb',__FILE__)
# this seems to cause these extra routes to be loaded last, so they will define named routes last.
end
end
You can test this routing sandwich in the console:
> Rails.application.routes.url_helpers.my_named_route_path
=> # before your fix, this will be the engine's named route, since it was defined last.
> Rails.application.routes.recognize_path("/route/you/want/to/stop/gem/from/controlling")
=> # before your fix, this will route to the controller and method you defined, rather than what the engine defined, because your route comes first.
After your fix, these calls should match each other.
(I posted this originally on the refinery gem google group here: https://groups.google.com/forum/?fromgroups#!topic/refinery-cms/N5F-Insm9co)

Rails - building an absolute url in a model's virtual attribute without url helper

I have a model that has paperclip attachments.
The model might be used in multiple rails apps
I need to return a full (non-relative) url to the attachment as part of a JSON API being consumed elsewhere.
I'd like to abstract the paperclip aspect and have a simple virtual attribute like this:
def thumbnail_url
self.photo.url(:thumb)
end
This however only gives me the relative path. Since it's in the model I can't use the URL helper methods, right?
What would be a good approach to prepending the application root url since I don't have helper support? I would like to avoid hardcoding something or adding code to the controller method that assembles my JSON.
Thank you
The url helper takes the host name from the incoming request. A model doesn't need a request to exist, hence why you can't use the URL helpers.
One solution is to pass the request hostname to the thumbnail url helper.
def thumbnail_url(hostname)
self.photo.url(:thumb, :host => hostname)
end
Then call it from your controllers / views like this
photo.thumbnail_url(request.host)
It turns out that there isn't really a foolproof way to get the host name of a server. If a user adds an entry to their /etc/hosts file, they can access the server with whatever host name they want. If you rely the incoming request's hostname, it could be used to break the thumbnails.
Because of this, I generally hardcode my site's host name in an initializer. e.g. put this in config/initializers/hostname.rb
HOSTNAME = 'whatever'
-- edit --
It looke like in rails 3 you have to provide the :only_path => false parameter to get this to work. Here's an example from the console:
>> app.clients_path :host => 'google.com', :only_path => false
=> "http://google.com/clients"
In Rails 3.0, the include given above results in a deprecation warning.
In Rails 3.0, use the following code instead to include url helpers:
class Photo < ActiveRecord::Base
include Rails.application.routes.url_helpers
end
I've found you can have URL helpers in models with the following:
class Photo < ActiveRecord::Base
include ActionController::UrlWriter
def thumb_url
thumb_url(self)
end
end
Caution though - I found this picked up the HOST, but not the port. You can investigate ActionController::default_url_options for more detail.

Resources