Is there a way to transform Rails params?
I have a URL like #some-user/posts/1
Users have the decorated # in the URL.
But, Users are saved without the # like.. some-user
So I need to look up the post via username without the #.
Currently, I have..
def url_params
params.permit(:username, :id)
end
Is there a best way to tranform the params for later use? In this case, remove the #?
One way to remove the # is like this:
‘#some-user’[1..-1]
As #jvillian has stated, this may not be the ‘best’ way, depending on your idea of ‘best’. For example, if you’re using Ruby 2.7, you can also use:
‘#some-user’.delete_prefix(‘#‘)
Maybe this is the ‘best’ way.
Ended up with this one.. I like this the best :)
def user_name
params[:username].gsub('#', '')
end
Related
I seem to find it difficult to get the username from a url with params, but works when finding IDs.
To get the id from this url: www.foo.com/users/1/post/new, you'd use:
User.find(params[:id]) # same as User.find(1)
I thought I could do the same, based on the docs, for: www.foo.com/users/joe/post/new
User.find_by(name: params[:name])
How to grab the user's name from url with params using the find or find_by method? Thanks
In your User model, override the to_param method like this:
def to_param
name
end
With this code, you're overriding the ActiveRecord default behaviour, so when you link to a User, it will use the name for the parameter instead of id.
Also, I recommend you to take a look at the friendly_id gem as well, using which you can achieve this goal.
I am developing an app in Rails 3.2 that uses the to_params to change the URL/route to a custom one.
The to_params in the model is something like this:
def to_params
keyword
end
Then, in the controllers, I look up the object using:
def show
#object = Object.find_by_keyword(params[:id])
end
I also have a before_save in the model that ensures all keyword entries are lowercase, so the URLs come out like http://mydomain.com/object/keyword.
My question is... Some users might be tempted to capitalize a keyword or something when putting it in the URL themselves. How can I convert that URL into lowercase before trying to find the object in the controller? I've tried #object = Object.find_by_keyword(params[:id].lowercase), but it didn't seem to work.
Any help would be greatly appreciated!
#object = Object.find_by_keyword(params[:id].downcase)
Should work
I have a model, let's say user, with both an id and a slug. I'd like to be able to generate a url using user_path(#user) that contains both the id and slug.
I know that user_path will use to_param method for the parameter it puts at the end of the url, but is there a way to use 2 (or more parameters) and get something like this:
http://domain.com/users/id/slug
Thanks!
Friendly-id is a great way to generate permalinks. It also offers pretty good customization options.
Did you try this in your model?
def to_param
"#{id}-#{slug)"
end
I have a basic CRUD with "Company" model. To make the company name show up, I did
def to_param
name.parameterize
end
Then I accessed http://localhost:3000/companies/american-express which runs show action in the companies controller.
Obviously this doesn't work because the show method is as following:
def show
#company = Company.find_by_id(params[:id])
end
The params[:id] is american-express. This string is not stored anywhere.
Do I need to store the short string (i.e., "american-express") in the database when I save the record? Or is there any way to retrieve the company data without saving the string in the database?
Send the ID with the parameterized value;
def to_param
new_record? ? super : "#{id}-#{name}"
end
And when you collect the data in the show method, you can use the whole parameter;
def show
#company = Company.find("12-american-express"); // equals to find(12)
end
There's also a plugin called permalink_fu, which you can read more about here.
I think friendly_id is more usable.
I do something similar with the Category model in my blog software. If you can guarantee that the only conversion the parameterize method is doing to your company names is replacing space characters with dashes then you can simply do the inverse:
def show
#company = Company.find_by_name(params[:id].gsub(/-/, ' '))
end
Try permalink_fu plugin, which creates SEO friendly URLs in rails
http://github.com/technoweenie/permalink_fu
cheers
sameera
I would suggest the friendly_id gem also.
It gives you the flexibility to use persited permalink slugs, also strip diacritics, convert to full ASCII etc.
Basically it makes your life a lot easier, and you get "true" permalinks (no to_param and the id workaround needed) with little effort.
Oh and did i mention that the permalinks are also versioned, so you can make old outdated permalinks to redirect to the current one? :)
I am dealing with a very simple RESTful Rails application. There is a User model and I need to update it. Rails coders like to do:
if #user.update_attributes(params[:user])
...
And from what I understand about REST, this URL request should work:
curl -d "first_name=tony&last_name=something2&v=1.0&_method=put" http://localhost:3000/users/1.xml
However, it's quite obvious that will not work because each URL parameter will be parsed to the variable "params" and not "params[:user]"
I have a hackish fix for now, but I wanted to know how people usually handle this.
Thanks
It's just a matter of how Rails parses parameters. You can nest parameters in a hash using square brackets. Something like this should work:
curl -d "user[first_name]=tony&user[last_name]=something2&v=1.0&_method=put" http://localhost:3000/users/1.xml
This should turn into
{:user=>{:last_name=>"something", :first_name=>"tony"}}
in your params hash. This is how Rails form helpers build the params hash as well, they use the square brackets in the form input tag name attribute.
It's a tradeoff; You can have slightly ugly urls, but very simple controller/models. Or you can have nice urls but slightly ugly controller/models (for making custom parsing of parameters).
For example, you could add this method on your User model:
class User < ActiveRecord::Base
#class method
def self.new_from_params(params)
[:action, :method, :controller].each{|m| params.delete(m)}
# you might need to do more stuff nere - like removing additional params, etc
return new(params)
end
end
Now on your controller you can do this:
class UsersController < ApplicationController
def create
#handles nice and ugly urls
if(params[:user]) #user=User.new(params[:user])
else #user = User.new_from_params(params)
end
if(#user.valid?)
... etc
end
end
end
This will handle your post nicely, and also posts coming from forms.
I usually have this kind of behaviour when I need my clients to "copy and paste" urls around (i.e. on searches that they can send via email).