How to get full asset path in rails model - ruby-on-rails

I'm using gmap4rails in my application which says to specify a marker you should define a method in your model. But how can i get full image url for that?
Now I have the following code in my model
def gmaps4rails_marker_picture
{
"picture" => helpers.asset_path("marker.png"),
"width" => 20,
"height" => 33
}
end
def helpers
ActionController::Base.helpers
end
But this only give me path for an image?
I've also tried to do it like this
Rails.application.routes.url_helpers.root_url + helpers.image_path("marker.png")
but that gives me an error:
Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
Any way to make this work?

Look at How to set config.action_controller.default_url_options = {:host = '#''} on per environment basis.
You need to set Rails.application.routes.default_url_options or to pass :host option to root_url(host: 'foo.bar')
To set different host option for different environments you can use ./config/environments/xx.rb files

Related

How to load and use root_url in Rails helper file?

In my Rails application_helper.rb file, I have a function that need to use root_url:
def get_post_link(post)
host = root_url
post_link = host + 'posts/' + post.id.to_s
return post_link
end
But then, when I am using this function, I will now get an error like this:
NoMethodError: undefined method `posts_path' for #<Module:0x007fa8978e54a8>
I search around for solution and I stumble upon this:
include Rails.application.routes.url_helpers
But when I include this line, another error comes out which is this:
ArgumentError: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
I know that I could simply supply the :host parameter to the root_url to solve this problem like this: root_url(:host => "localhost:3000") but this just defeating the purpose of why I wanna use the root_url in the first place. This is because I am now just hardcoding the root_url and there is no way for the code to intelligently know whether I want the production server url or my localhost url like it originally suppose to do.
So, is there any other way to do this? So i could correctly use the root_url in my application_helper?
Thanks!

How to add a trailing_slash to all urls without in Rails 4?

I've tried adding this in application.rb
config.action_controller.default_url_options = { :trailing_slash => true }
as well as having :trailing_slash => true in routes.rb
match '/download', to: 'welcome#download', via: 'get', :trailing_slash => true
But neither seems to work. I searched through rails 4.0 doc but couldn't find related info. What am I missing here?
Update:
I've tried adding
Rails.application.default_url_options[:trailing_slash] = true
in filter_parameter_logging.rb since this is the only place in the whole project where I could find Rails.application.*, but it's not working either. I found the line here among the releases and I am using 4.0.4. Am I adding this in the wrong place? And I did restarted server before rechecking.
And sorry for the simple question but from what I've gathered isn't trailing_slash supposed to be reflected in browser url as well, if not primarily? Because this is what I need, to go with historyjs.
I think you have the meaning of :trailing_slash => true wrong.
All it does is add the / to the end of you path helpers. No redirecting involved.
Your routes will still respond to both with and without the trailing slash.
If you want to redirect all non-trailing_slash uri's like /download to /download/ using a nginx http server you would do something like this:
rewrite ^([^.\?]*[^/])$ $1/ permanent;
You would still want to add the :trailing_slash => true to your routes so your path/url helpers generate the the correct uri's (so user don’t need to redirect).
Trailing_slash refers to a / after the name like page/ not like /page.
You have given your routes wrongly.
Change it to
match 'download/', to: 'welcome#download', via: 'get', :trailing_slash => true
There is also other way to achieve this by giving a trailing_slash => true option directly to your link_to helper.
link_to 'Downloads', downloads_path(:trailing_slash => true)
Though this work in Rails 3,not sure about Rails 4.
For more details see this SO.
I am using rails 4.0.2 for me it's working
routes.rb
get 'admin/update_price_qty' => 'admin#update_price_qty', :trailing_slash => true,:as => "price"
in console :-
irb(main):003:0* app.price_path
=> "/admin/update_price_qty/"
routes.rb
match '/download', to: 'welcome#index', via: 'get', :trailing_slash => true,:as => "welcome_price"
in console :-
`irb(main):002:0> app.welcome_price_path
=> "/download/"`
But I've tried adding this in application.rb
config.action_controller.default_url_options = { :trailing_slash => true }
not working.
You may add this line to config/application.rb:
config.action_controller.default_url_options = { trailing_slash: true }
If you do this, when you call a Rails path helper inside a controller or helper, the generated path will have a / at the end:
class ApplicationController
def index
download_path # returns "/download/"
end
end
module PathHelper
def path
download_path # returns "/download/"
end
end
If you need to use path helpers outside controllers and helpers, you need to include Rails.application.routes.url_helpers, but apparently, this ignores the trailing_slash configuration above:
class SomeClass
include Rails.application.routes.url_helpers
def path
download_path # returns "/download"
end
end
In this case, you should add { trailing_slash: true } as a parameter:
class SomeClass
include Rails.application.routes.url_helpers
def path
download_path(trailing_slash: true) # returns "/download/"
end
end

Rails: configuring a form action's host using custom URL from settings

I have a Rails app that I am feeding cross domain in production. It needs absolute references. Because of this, I have enabled the following in my config/environments/production.rb:
config.action_controller.asset_host = "http://myapp.herokuapp.com"
That works fine for images and resources but my input form that looks like this:
<%= form_tag('/plans/collapse_plans', :method => 'post', :remote => true ) do %>
is still getting this in the console:
Failed to load resource file://localhost/plans/collapse_plan
How can I change it so that form action will automatically include the specified host, instead of defaulting to localhost? Can I set this anywhere in config?
This seems like it will work:
https://github.com/binarylogic/settingslogic
Then I can just do:
<%= form_tag mysettings.myspecifiedhost + plans_collapse_plans_path, :method => 'post', :remote => true do %>
I may be on the wrong track here, but:
Asset host is not your application's host, asset host is a host that serves you /app/assets folder and this is configurable so you can set up a CDN for example, it's not intended for hosting action points.
If you want to target the full url of your own host use rake routes to get the route name corresponding to /plans/collapse_plans which probably looks something in the lines of plans_collapse_plans and then you can use plans_collapse_plans_url and rails will render the correct full URL for you.
If you're using the default host name rails provides automagically this will "just work", i.e.
[2] pry(#<#<Class:0x000000048fd780>>)> account_edit_url
=> "http://dev:3000/account/edit"
If this doesn't "just work", you can override all url helpers in the app by overriding default_url_options in your ApplicationController:
def default_url_options
{:host => HOST}
end
and be sure to set the HOST constant in your application's environment, for example:
[1] pry(#<#<Class:0x00000005047d10>>)> account_edit_url
=> "http://o7ms:3000/account/edit"
If you need to override this just in certain situations you can leave the ApplicationController alone and do:
[3] pry(#<#<Class:0x000000048fd780>>)> account_edit_url(host: MY_HOST_FOR_THE_OTHER_THINGY)
=> "http://foo:3000/account/edit"
In all cases you'll set up a config option in one place and all endpoints in the app will adjust.
EDIT
If you want to go fancy,
see default_url_options and rails 3,
by overriding url_options you may be able to implement pretty calls like account_edit_url(ajax_host: true), the url_options method would look something like this if this works:
def url_options
options = super
if super.delete(:ajax_host)
{host: AJAX_HOST}.merge(options)
else
options
end
end
what you are trying cannot be done normally for ajax calls.
see http://en.wikipedia.org/wiki/Same-origin_policy
Two approaches:--
1.) <%= form_tag root_url + plans_collapse_plans_path, :method => 'post', :remote => true do %>
concatenation:-- root_url + plans_collapse_plans_path
2.) in config/environments/production.rb
MyApp::Application.configure do
# general configurations
config.after_initialize do
Rails.application.routes.default_url_options[:host] = 'root_url' #'localhost:3000'
end
end

url_for not using default_url_options[:host] value

I've got a view for an ActionMailer that includes a few different links. I'm running it on localhost:3000 right now, and so I've set that as such in a file called setup_mail.rb in app/initializers (as indicated here):
ActionMailer::Base.default_url_options[:host] = "localhost:3000"
When I go to use url_for in the view, it doesn't seem to pull this value. If I then add :host => "localhost:3000" to each url_for tag, they work properly. But they don't work without that included.
I have another tag, project_url, which is as it appears: a link to a specified Project. This functions, including the host value, with just project_url(#project). Why would one work but not the other?
From everything I've read, setting the default_url_options[:host] in an initializer should allow me to omit the :host value in the url_for tag. Obviously, it's not the worst thing in the world to just add that value, but it seems unnecessary and it means that when I eventually host the project somewhere I'll have to go through and change that value all over the place. But worse than that, it's something that I don't understand. I'm still learning as I go here and so I'd like to know what I'm doing wrong.
The documentation is pretty clear on this
When you decide to set a default :host for your mailers, then you need to make sure to use the :only_path => false option when using url_for. Since the url_for view helper will generate relative URLs by default when a :host option isn’t explicitly provided, passing :only_path => false will ensure that absolute URLs are generated.
You could create your own helper to use instead of the url_for to force :only_path to be false
def your_url_for(options = {})
options.reverse_merge! only_path: false
url_for(options)
end
You could also monkey patch rails to force this as the default, but that's left up to you :)
This all would be in addition to adding
config.action_mailer.default_url_options = { host: "YOUR HOST" }
to config/application.rb or equivalent.
It seems :only_path option is false which is by default. so that is why you need to provide [:host] either explicitly for every tag or set default options for url_for which would apply to all tags. here is how to set default host:
put this code in your Application controller & it should work.
helper_method :url_for
def default_url_options(options)
{ host: 'localhost:3000' }
end
For more details check set url_for defaults
Instead of tampering with the global default setting which imho shouldn't be changed after initialization you can simply define a method default_url_options in your mailer just like you can do it in a controller:
class UserMailer < ActionMailer::Base
def default_url_options
{ host: Tenant.current(true).host }
end
def confirm(user)
#user = user
mail(to: #user.email, subject: t(".subject_confirm"))
end
end
You're setting the default in ActionMailer::Base, but appear to expect it to reset the default for ActionController::Base.
A <%= link_to %> inside your mailer view doesn't necessarily know anything about the fact that it's inside a mailer view.

Full URL with url_for in Rails

How can I get a full url in rails?
url_for #book is returning only a path like /book/1 and not www.domain.com/book/1
Thanks (and sorry if the answer is obvious. Im learning rails!)
According to the docs, this shouldn't happen. The option you're looking for is :only_path and it's false by default. What happens if you set it to false explicitly?
url_for(#book, :only_path => false)
While you can use url_for you should prefer Ryan's method when you can - book_url(#book) for a full url or book_path(#book) for the path.
If it's a RESTful resource you'll be able to use this:
book_url(#book)
In Rails 4, url_for only takes one argument, so you need to pass an array with an explicit hash inside for the only_path option.
Good:
url_for([#post, #comment, {only_path: true}])
Bad:
url_for(#post, #comment, {only_path: true})
url_for([#post, #comment], {only_path: true})
From the source, url_for with an Array input just calls:
polymorphic_url([#post, #comment], {only_path: true})
as shown in #moose's answer.
As noted by #lime, only_path is generally not needed for polymorphic_url since you distinguish that with the _url _path suffixes.
It seems that this would work:
url_for(#book)
But it does not. The url_for method accepts only one argument, which can be either a string, an instance of a model, or a hash of options. This is rather unfortunate, as it would seem like you may need to link to #book and add options like :only_path or :host as well.
One way around it is to use polymorphic_url, which would render the correct absolute url even though your model is (likely) not actually polymorphic:
polymorphic_url(#book, :host => "domain.com")
Perhaps the best route would be to use a named route, which is set up automatically for you when declaring resources in your routes or using the :as option:
# in routes.rb:
resources :books
# or
get "books/:id" => "books#show", as: :book
# in your view:
book_path(#book, :host => "domain.com")
Use the :host option. For example, you can use:
url_for(#book, :host => "domain.com")
Note: with Rails 3 and above, use polymorphic_url instead of url_for.
In Rails 5, if you want the full url for the current controller/action (== current page), just use:
url_for(only_path: false)
Long answer:
In Rails 5, url_for in a view is ActionView::RoutingUrlFor#url_for. If you look at it's source code (https://api.rubyonrails.org/classes/ActionView/RoutingUrlFor.html#method-i-url_for), you'll see if you pass a Hash (keyword parameters are cast into a Hash by Ruby), it actually calls super, thus invoking the method of same name in it's ancestor.
ActionView::RoutingUrlFor.ancestors reveals that it's first ancestor is ActionDispatch::Routing::UrlFor.
Checking it's source code (https://api.rubyonrails.org/classes/ActionDispatch/Routing/UrlFor.html#method-i-url_for), you'll read this:
Missing routes keys may be filled in from the current request's
parameters (e.g. :controller, :action, :id and any other parameters
that are placed in the path).
This is very nice, since it will build automatically a URL for you for the current page (or path, if you just invoke url_for without the only_path: false). It will also intelligently ignore the query string params; if you need to merge those, you can use url_for(request.params.merge({arbitrary_argument:'value'})).

Resources