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
Related
I am trying to pass a simple variable in my params to a class method, however it doesnt seem to work. This seems elementary, but I'm still learning. Can someone explain why this doesn't work and offer an alternative? My code is below.
controller
#profile = current_user.profile
#dogs = Dog.by_profile(params[#profile])
model
def self.by_profile(profile)
Dog.where(kids_under_10: profile.kids_under_10 )
end
*note: profile.kids_under_10 is a boolean. When I manually replace it with true or false, everything works fine.
params is a special rails hash that contains url parameters. So your code is looking for a url parameter passed with the request containing the string version of your user profile. This is definitely not what you want to be doing.
When you're calling a rails model method, you call it with arguments like any other method: Dog.by_profile(#profile)
You don't want the params part, or you're trying to do something crazy that should be refactored :)
Your key value for params should look like params[:profile].
So try #dogs = Dog.by_profile(params[:profile]).
Because params is a hash that comes from a request. What you are doing is trying to search the hash with an instance variable which is wrong.
I think what you meant is to do params[:profile] or just #profile
Having some issues, I want my urls for the show action to be like:
/post/some-title
i.e. so wherever I reference the show_post_path tag (or whatever it is) it should make that url.
BUT, when editing/updating I want to do this using the ID of the post ie.
/post/234/edit
How can I achieve this, it seems what I am doing is messing things up because I used:
def to_param
#{title}"
end
In my post model.
I always add an attribute called 'slug' to posts and it acts as a slug for that post.
Then just find your posts with Post.find_by_slug(params[:id]).
You can even make it translatable.
Create a to_param method. For example:
def to_param
"#{self[:id]}-#{title.gsub(/[^a-z0-9]+/i, '-')}"
end
Assuming the field you wanted to be in the URL is title, then your posts' URLs would be like /posts/1-this-is-a-post.
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).
I am currently developing a blogging system with Ruby on Rails and want the user to define his "permalinks" for static pages or blog posts, meaning:
the user should be able to set the page name, eg. "test-article" (that should be available via /posts/test-article) - how would I realize this in the rails applications and the routing file?
for user-friendly permalinks you can use gem 'has_permalink'. For more details http://haspermalink.org
Modifying the to_param method in the Model indeed is required/convenient, like the others said already:
def to_param
pagename.parameterize
end
But in order to find the posts you also need to change the Controller, since the default Post.find methods searches for ID and not pagename. For the show action you'd need something like this:
def show
#post = Post.where(:pagename => params[:id]).first
end
Same goes for the other action methods.
You routing rules can stay the same as for regular routes with an ID number.
I personally prefer to do it this way:
Put the following in your Post model (stick it at the bottom before the closing 'end' tag)
def to_param
permalink
end
def permalink
"#{id}-#{title.parameterize}"
end
That's it. You don't need to change any of the find_by methods. This gives you URL's of the form "123-title-of-post".
You can use the friendly_id gem. There are no special controller changes required. Simple add an attribute for example slug to your model..for more details check out the github repo of the gem.
The #63 and #117 episodes of railscasts might help you. Also check out the resources there.
You should have seolink or permalink attribute in pages' or posts' objects. Then you'd just use to_param method for your post or page model that would return that attribute.
to_param method is used in *_path methods when you pass them an object.
So if your post has title "foo bar" and seolink "baz-quux", you define a to_param method in model like this:
def to_param
seolink
end
Then when you do something like post_path(#post) you'll get the /posts/baz-quux or any other relevant url that you have configured in config/routes.rb file (my example applies to resourceful urls). In the show action of your controller you'll just have to find_by_seolink instead of find[_by_id].