Pretty urls (friendly_id gem) with dots - ruby-on-rails

Many solutions are available for rails 2 but none for rails 3.1 because the map object has been removed.
Any solution for this problem in the latest rails?

I have had to do this recently on a project. Luckily, it's simple to override the slug-generating method on a per-model basis.
please refer to
https://github.com/norman/friendly_id/blob/master/lib/friendly_id/slugged.rb#L113-116
and
https://github.com/norman/friendly_id/blob/master/lib/friendly_id/slugged.rb#L227-231
you should be able to define this on the model:
# Use default slug, but upper case and with underscores
def normalize_friendly_id(string)
super.upcase.gsub("-", ".")
end
Hope this helps.
Note: This method is available in FriendlyId 3.x as well. It's great for defining a custom regex for generating slug strings.

Related

Do these remarks in a generated rails scaffold do anything?

When I generate a scaffold in rails, I noticed that the methods are prefaced with # remarks. I haven't been able to find any documentation as to if they actually do anything of if they are similar to what looks like remarks in application.js that look like remarks but are really code.
For example:
# POST /attachments
# POST /attachments.json
def create
and
# GET /attachments/1
# GET /attachments/1.json
def show
end
I am using rubymine as my editor.
No, they don't do any magic behind the scenes. They are just comments to help you out.
By default, scaffolding will direct POST requests to create(), and GET of a particular resource (e.g. /resources/<id>) to show(). These associations are defined in your routes, and scaffolding applies this convention. You're free to change them in your routes if you wish.
Those are just comments in Ruby. They are ignored by the Ruby interpreter and are meant for the developer.

Auto-generate transliterated cyrillic slugs with friendly_id

I want to implement friendly_id into existing model. Application uses russian gem, which handles new or hand-saved records well, but it doesn't seem to work when I update records from the command line.
User.find_each(&:save) (as friendly_id docs syggested) generate slugs like --<id>.
I used custom normalize method to provide transliterated slug:
def normalize_friendly_id(input)
Russian.transliterate input.to_s.mb_chars.downcase
end
but it definitely may miss some edge cases, and handles string differently from "normal" workflow. What I'm looking for is the way to reuse regular create/update flow and native behavior.
The best way to resolve this problem:
1) Add gem 'babosa' n your Gemfile
gem 'friendly_id'
gem 'babosa'
2) Owerride friendly_id's method in your model
def normalize_friendly_id(text)
text.to_slug.transliterate(:russian).normalize.to_s
end

Rails 4 engine with nested namespace

I could not find a way to generate engines with nested namespaces under rails. Every time I do that, I basically have to edit and move around the generated files by hand.
Is there really no support for nested namespaces in rails? Seems unlikely.
At the company we namespace everything like this:
CompanyName::SerivceName::Module
So when I'm working on Service1, and making the engine which will be integrated into the app that customer support uses to play around with the users and data of that service on customer requests, I'd like to create that engine under
CompanyName::Serive1::CustomerSupport
However rails seems to be unable to do that.
Using rails plugin new a::b::blah is not accepted:
akovanm0:test avandra$ rails plugin new a::b::blah -T --dummy-path=spec/dummy --mountable --full --mountable
Invalid plugin name a::b::blah. Please give a name which use only alphabetic or numeric or "_" characters.
Specifying rails plugin new a/b/blah generates an engine, but has the same output as rails plugin new blah
Specifying rails plugin new a_b_blah generates an engine with the literal name a_b_blah, not namespaced. (and the actual name is camelcased to ABBlah)
What I'd like to achieve is an engine whose controllers, models and views are generated under the a::b::blah namespace, and it is mountable the same way.
I want all generated controllers to go under app/controllers/a/b/blah, the models to go under app/models/a/b/blah, and so on...
Is there a way to achieve this?
For anyone reading this in 2022, I believe later versions of Rails handle engine names with dashes as separate namespaces.
rails plugin new parent_engine-sub_engine --mountable
Will create the following engine.rb:
module ParentEngine
module SubEngine
class Engine < ::Rails::Engine
isolate_namespace ParentEngine::SubEngine
end
end
end
You need to create engine with mountable option enabled like this,
rails plugin new engine_name --mountable.
It will add isolate_namespace EngineName method call in lib/engine_name/engine.rb to isolate engine namespace.
I think you can't do that :(
EDIT: Look at the bottom of the answer, I have modified the rails plugin generator just to do it :)
If you look carefully to the source (https://github.com/rails/rails/blob/5f07366bed77116dbfbb5b98d1cdf6c61b3dfc9b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb#L299) you will see that the plugin name is just the basename of the destination folder.
def original_name
#original_name ||= File.basename(destination_root)
end
So if you write rails plugin new a/b/c then the plugin will be created at the a/b/c subfolder in your current folder but the name will be just c :(
If you override that original_name method to return a/b/c as desired then you will need to fight both the valid_const? method (https://github.com/rails/rails/blob/5f07366bed77116dbfbb5b98d1cdf6c61b3dfc9b/railties/lib/rails/generators/rails/plugin/plugin_generator.rb#L307) that validates the format name and accepts "only alphabetic or numeric or _ characters." and the templates that creates the modules.
def valid_const?
if original_name =~ /[^0-9a-zA-Z_]+/
raise Error, "Invalid plugin name #{original_name}. Please give a name which use only alphabetic or numeric or \"_\" characters."
elsif camelized =~ /^\d/
raise Error, "Invalid plugin name #{original_name}. Please give a name which does not start with numbers."
elsif RESERVED_NAMES.include?(name)
raise Error, "Invalid plugin name #{original_name}. Please give a name which does not match one of the reserved rails words."
elsif Object.const_defined?(camelized)
raise Error, "Invalid plugin name #{original_name}, constant #{camelized} is already in use. Please choose another plugin name."
end
end
I'm thinking on using a plugin template (http://edgeguides.rubyonrails.org/rails_application_templates.html) for my namespaced plugins instead :(
EDIT: I lied about what methods you would have to fight. It's not the name method, it's the templates
EDIT (II): I have modified the plugin_new folder so nested namespaces are allowed. You have it here: https://github.com/brenes/nested-plugin-generator
I would appreciate any feedback :)
Try https://github.com/T-Dnzt/Modular-Engine or create your own generator

Using titleize for acronym in Rails

I am defining some active records with acronyms. RvPark (Recreational Vehicle Park). When I titleize the class name, I get 'Rv Park'. It really should be 'RV Park'. Is there a good way to do this? Since this model shares code with other models, I need to create a generic solution, but I haven't been able to come up with one.
I did see a discussion on this, but there wasn't a solution that worked for me. any insight is appreciated.
https://rails.lighthouseapp.com/projects/8994/tickets/2944-titleize-doesnt-take-all-uppercase-words-into-account
You can do this by configuring ActiveSupport::Inflector, which provides the titleize method. Simply define your own inflections in an initializer.
# config/initializers/inflections.rb
ActiveSupport::Inflector.inflections do |inflect|
inflect.acronym 'RV'
end
Restart your app to pick up the change. Now titleize knows how to handle "RV". Fire up a Rails console to check it out:
> "RvPark".titleize
=> "RV Park"
> "rv".titleize
=> "RV"
See the linked docs for more cool stuff you can do with inflections.
UPDATE: Acronym support was added to the Rails Inflector after I posted this.
See #Anson's answer for Rails 3.2 and up.
This looks like an edge-case that titleize wasn't designed for. The problem is the capitalize call inside will always turn RV into Rv.
I would create a generic name function for the models that call self.class.titleize internally, and then overload it in the RVPark model.

Uninitialized content when trying to include ActionController::UrlWriter in model

I'm using Rails 3 beta 4 and trying to include ActionController::UrlWriter in my model, which is the correct way to go about it as far as i can tell, but i get "Uninitialized Constant ActionController::UrlWriter".
Any idea why that would be? Did it move in rails 3?
First I agree with zed. This shouldn't be done in a model. Your models should be unaware of any http url.
I do the same in a resque job. Here's what I do :
include ActionDispatch::Routing::UrlFor
include ActionController::PolymorphicRoutes
include Rails.application.routes.url_helpers
default_url_options[:host] = 'example.com'
Then you can call any usual url generator.
url_for(object)
page_url(object)
It'll create the link on the host defined as default_url_options[:host]
Answers to Can Rails Routing Helpers (i.e. mymodel_path(model)) be Used in Models? are pretty good
or see
http://api.rubyonrails.org/classes/ActionDispatch/Routing/UrlFor.html
http://siddharth-ravichandran.com/2010/11/26/including-url-helpers-in-models/
Basically, you can do something like this in a model:
def url
Rails.application.routes.url_helpers.download_attachment_path(self)
end
It is worth considering whether this is the right layer, though. In my case it's for file attachments and I want to do attachment.url instead of writing out a helper a lot.

Resources