Routes - how to display in url ID and the name of article? - ruby

I have the Articles controller and for displaying the respective article I use the basic routes - example.com/articles/4.
I would like to change this URL format to example.com/4-article-name or example.com/article-name-4.
Could anyone give me a tip, how to do that?
Thanks

Ryan Bates(Railscast.com) seems to have done an episode that solves your problem:
/app/models/article.rb
class Article < ActiveRecord::Base
def to_param
"#{id} #{name}".parameterize
end
end
See: http://railscasts.com/episodes/314-pretty-urls-with-friendlyid?view=asciicast

Generally numbers on the beginning is the most elegant way, since in ruby it could be very easily converted to integer, for instance '123-foo-bar'.to_i will return 123.
See http://apidock.com/rails/ActiveRecord/Base/to_param you'll find how to change this mechanism.

Related

How can you make the id in the URL be random?

So I am looking for a way to create a randomized id that will link to a lobby that will be shown when the shown method is called in rails. As of right now, the url would look like this: http://localhost:3000/lobby/2. I'm looking to replace that 2 with a randomly generated id so you could send that link to friends if you want them to join your lobby. Any ideas?
You should share a bit more information as Gavin said. Knowing what you have already tried can help us give you more/better information on how to proceed.
I hope this sends you the right direction. For generating random IDs you can use SecureRandom:
http://ruby-doc.org/stdlib-1.9.3/libdoc/securerandom/rdoc/SecureRandom.html
I'd recommend you add another column to the lobbies table, and make it unique:
add_column :lobbies, :secure_token, :string, null: false
add_index :lobbies, :secure_token, unique: true
Now, in your Lobby model, whenever it is created, you can generate a unique token. For simplicity, you can do something along these lines:
class Lobby < ActiveRecord::Base
before_create :generate_unique_secure_token
# Rest of the model's code
private
def generate_unique_secure_token
begin
self.secure_token = SecureRandom.urlsafe_base64
end while self.class.exists?(secure_token: secure_token)
end
end
This will generate a secure_token every time a Lobby is created. Now in the controller you can use the secure_token instead of the id to find your Lobby. For example:
class LobbiesController < ApplicationController
def show
#lobby = Lobby.find_by(secure_token: params[:id])
end
end
I won't give you the whole answer since it's great to learn these things, but if you have any questions feel free to ask me!
This is where you should start: URLSafe Base 64
Here's a Railscasts episode that's soft of similar to what you want, see if you can expand from there! If you're new to Rails, be sure to check out Railscasts. All the pro episodes are available for free on youtube!

Rails 4: Append to a "has_many" relation without saving to DB

In Rails 3 one can do things like some_post.comments.append(some_comment) where some posts is an instance of a model that "has_many" comments.
The problem I'm facing in Rails 4 is that the append method now saves to DB (like push and << ) and I need to just "append" without saving the appended object to the DB.
How do we achieve that in Rails 4? I can't use some_post.comments.build(some_comment.attributes) because I need to preserve the other relations already present in the some_comment instance.
It's oddly difficult to do this elegantly in Rails. This is the cleanest way I've found:
post.association(:comments).add_to_target(comment)
You could do:
class Post < ActiveRecord::Base
has_many: comments, autosave: false
...
end
Then << will just append and not save.
You can do it without using reflection on the association:
post.comments.build(
attr_1: value_1,
attr_1: value_2,
# Other comment attributes
)

Twitter Ruby Gem

I am trying to setup the Twitter gem, and I feel like I'm almost there... kind of.
Right now I was trying to follow this link:
http://www.phyowaiwin.com/how-to-download-and-display-twitter-feeds-for-new-year-resolution-using-ruby-on-rails
It is a bit old though, and I guess its instructions are a bit out of date. I have created a twitter model, twitter db migration and a twitter controller(not sure it's needed though), and if i open rails console, and I type:
Twitter.user_timeline("whatever").first.text
It just works. I just can't seem to be able to see it in my view. can you point me in the right direction?
Thanks a lot!
Alex
In your controller that corresponds with your view, you need to assign your results to a variable inside the appropriate functionlike so:
def controller_function
#twitter_data = Twitter.user_timeline("whatever").first.text
end
Then, in your corresponding view you can use the variable
<%= #twitter_data ... %>
Check out http://guides.rubyonrails.org/layouts_and_rendering.html for more guidance on controllers and views

Trouble passing value from view to controller in Rails 3.1.1

I have two model Product and Category, they have has_many, and belongs_to association respectively. Now, what I am trying to do is when I click on particular category I want all the products of that category to be listed. How do I do that
here is my view
<p><%=link_to #product.category.name, show_by_category_products_path(#product.category.id)%> <%= #product.name%> <%=#product.category.id%><p>
and method in controller
def show_by_category
#products = Product.where("category_id=?", :id)
end
Thanks! (I know its simple stuff, but sometimes you get blind and can't see a straightforward way so you have to sought help of others)
EDIT
okay maybe I figured out a way to go around this.. but I am not sure if it is done in right way
Now my view and model looks something like this
<p><%=link_to #product.category.name, show_by_category_product_path(id: #product.id)%> <%= #product.name%>
def show_by_category
#prod = Product.find(params[:id])
#products = Product.where('category_id=?', #prod.category_id)
end
Tell me if this is right way?
Your find should look more like Category.find(params[:id]).products. But try to follow RESTful routing principles, and nest your resources. Rails will do much more for you.
I would recommend you to read at least Getting Started guide, because you are doing it wrong.

Rails 3. Leaving wrong value of integer attributes in a form

I have model 'Human' and this model has integer attribute :age.
For example, I use validation for this integer attribute :age.
When I add new 'Human' with wrong value of :age (e.g. "2aaa3") it is render me back with error, but it is also cut :age like "2". But I don't want it. I want to leave last wrong value "2aaa3".
So, question is "How can I do it?"
That is the default behaviour of validation in Rails. Not sure if there are any other ways to override it. You could however do that validation using javascript, which will be much more user experience oriented than using validates_numericality_of.
Hi everybody who is interested in my question.
I am glad to say I've created solution by myself.
But I have several remarks to that. ))
First, the solution is:
class ApplicationController < ActionController::Base
...
...
after_filter :restore_int_value, :only => [:create, :update]
...
...
private
...
...
def restore_int_value
response.body = response.body.gsub(/(numeric.*<input id=")([^_]*)(_)([^"]*)(.*value=")(\d+)(")/){$1 + $2 + $3 + $4 + $5 + params[$2][$4] + $7}
end
...
...
end
Second, remarks are:
1) the solution works along such gems as 'Formtastic' and 'Simple_form'. These gems build the forms wraped in detailed html and give us possibility to use regex.
If you don't use such gems you can just wrap all your integer attributes, for example, in 'p' tag with 'numeric' class like following and I think my solution will work for this too:
<p class="numeric"> <%= text_field(:human, :age) %> </p>
2) I think my solution will not work for integer fields of nested models in multiple-models-form. (Ryan Bates describes such kind of work in "Handle Multiple Models in One Form" from "Advanced Rails Recipes").
But if you read Ryan Bates' article you will see that he already uses JavaScript. So, working with nested models in form you need JavaScript. Then you can use JavaScript for validation too (as Kunday told). And you will not have a problem. ;)
But if you have static number of nested models in form and do not use JavaScript, then I think you can create new particular regex for your needs (similar to the one I created). I hope you will manage with this. ;)
I hope I've covered all scenarios where you can have such problem and my solution will be useful for somebody, besides me. ;)

Resources