Ruby on Rails - generating bit.ly style identifiers
You are confusing two different things here. A UUID is a universally unique identifier. It has a very high probability of being unique even if millions of them were being created all over the world at the same time. It is generally displayed as a 36 digit string. You can not chop off the first 8 characters and expect it to be unique.
Bitly, tinyurl et-al store links and generate a short code to represent that link. They do not reconstruct the URL from the code they look it up in a data-store and return the corresponding URL. These are not UUIDS.
Without knowing your application it is hard to advise on what method you should use, however you could store whatever you are pointing at in a data-store with a numeric key and then rebase the key to base32 using the 10 digits and 22 lowercase letters, perhaps avoiding the obvious typo problems like 'o' 'i' 'l' etc
EDIT
On further investigation there is a Ruby base32 gem available that implements Douglas Crockford's Base 32 implementation
A 5 character Base32 string can represent over 33 million integers and a 6 digit string over a billion.
Best way to generate bit.ly or twitpic style ids?
Here's an example on I did it in Sinatra.
https://github.com/chrisledet/shorty_url
Are there style checker for Ruby code as JSLint for javascript
There's this tool named rails_best_practices but it's Rails-specific, not general Ruby, and it acts more as a guideline.
bitly raise error exception rspec test
As you can see from the docs - https://www.relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/raise-error-matcher - the raise error matcher can take a second parameter of string or regex to match against the exceptions message
expect { whatever }.to raise_error(BitlyError, "ALREADY_A_BITLY_LINK")
Generating Post ID's like Facebook and similar sites
- What are some advantages/disadvantages to using either approach?
Using sequential numbers
Advantages: Easy to implement
Disadvantages: Possible vector for attack. See this video for a high-level overview.
Using random numbers
Advantages: Solves the problems outlined in the video re: sequential record attacks
Disadvantages: Since there's only 10 bits of entropy, ID's would have to be much longer if your app grows.
Base 64 (use this instead of hex)
Advantages: 64 bits of entropy means an ID 5 chars long would have 64^5 possible permutations. This allows for comparatively much shorter URLs. Use SecureRandom.urlsafe_base64
for this.
Disadvantages: None, really.
- Is there a good industry standard or best practice for generating synthetic ids for concepts like users, groups, posts, etc..
To my knowledge, no. Anything sufficiently random and of sufficient length should be fine. Within your model, you'd want to check if an ID is taken first so you don't have duplicates, but outside of that there's little to worry about.
- What's the best way in Ruby/Rails to generate each of these IDs? I know of SecureRandom.hex but that seems to generate a long hash.
Like I said above, I recommend using SecureRandom.urlsafe_base64
Getting a HAML button_to work with twitter bootstrap
If you're trying to get a button tag in HAML you can use the %button
tag to generate it.
In order to change the class you would be able to do %button.class
ex.
%button.alert
Test
Would generate
<button class="alert">Test</button>
EDIT:
Just a bit extra, while I'm not experienced with using Bootstrap (I used Foundation), if you're interested in using button_to
you're allowed to declare the class, though it won't generate the tag you're looking for so this part is not related to your question.
= button_to 'Example, {:controller => 'your_controller', :action => 'your_action'}, {:class => 'your button class', :method => 'post'}
However this will generate a
<input class="small button" type="submit" value="Example">
Associate different models in the same relation
I would suggest using combination of store_accessor and STI. The store accessors will allow you to add model specific attributes with support for validation. If you use PostgreSQL you can take advantage of GIN/GiST index to search custom fields efficiently.
class User < ActiveRecord::Base
has_many :friends
end
class Friend < ActiveRecord::Base
belongs_to :user
# exclude nil values from uniq check
validates_uniqueness_of :user_id, allow_nil: true
# The friends table should have a text column called
# custom_attrs.
# In Postgres you can use hstore data type. Then
# next line is not required.
store :custom_attrs
# Shared between all friend models
store_accessor [ :shared_interests ]
validates_presence_of :shared_interests
# bit of meta-programming magic to add helper
# associations in User model.
def self.inherited(child_class)
klass = child_class.name
name = klass.pluralize.underscore.to_sym
User.has_many name, -> {where(type: klass)}, class_name: klass
end
end
Define various friend models with model specific attributes.
class BestFriend < Friend
store_accessor [ :favourite_colour ]
validates_presence_of :favourite_colour
def to_s
"This is my best friend whos favourite colour is #{favourite_colour} ..."
end
end
class RegularFriend < Friend
store_accessor [ :address ]
validates_presence_of :address
def to_s
"This is a regular friend who lives at #{address} ..."
end
end
class CloseFriend < Friend
store_accessor [ :car_type ]
validates_presence_of :car_type
def to_s
"This is a close friend who drives a #{car_type} ..."
end
end
Usage
user = User.create!
user.close_friends.create!(
car_type: "Volvo",
shared_interests: "Diving"
)
user.regular_friends.create!(
country: "Norway",
shared_interests: "Diving"
)
user.best_friends.create!(
favourite_colour: "Blue",
shared_interests: "Diving"
)
# throws error
user.best_friends.create!(
shared_interests: "Diving"
)
# returns all friends
user.friends.page(4).per(10)
Reference
Store documentation
PostgreSQL Hstore documentation:
Rails loop: Show and hide element by id
Your problem is scoping: you're not providing a context to document.getElementById("categories");
, meaning it just selects the first element on the page with the id
'categories'.
While we're here, id
should be unique to a page, so you're better switching anything rendered multiple times to use class
.
To use the scope to the click event you can pass the event
to the function, which we can use to find which li
it is toggling.
So in your html:
<li onclick="showHide(event)">
And your function:
function showHide(e) {
var parentCategory = e.currentTarget
var categoryList = parentCategory.querySelector(".categories"); // << assuming you switch to using classes
if(!categoryList) { return }
if (categoryList.style.display === "none") {
categoryList.style.display = "block";
} else {
categoryList.style.display = "none";
}
}
That way, you're looking for the categories within the clicked li
, and you should see this toggle as expected.
You can also slim this down a little using a ternary if you're using es6:
function showHide(e) {
let categoryList = e.currentTarget.querySelector(".categories");
if(!categoryList) { return }
categoryList.style.display = categoryList.style.display === "none" ? "block" : "none"
}
Let me know how you get on, of if you have any questions.
Related Topics
How to Add Attribute to Nokogiri Node
Getting Remove_Entry_Secure Error While Using Ruby Application
How to Retrieve Exif Information of an Image in Rails
How Do Open a File for Writing Only If It Doesn't Already Exist in Ruby
How Does One Match Character or Nothing Using Regular Expression
Rails: Faster Way to Perform Updates on Many Records
Ruby Time.Parse Gives Me Out of Range Error
Working with a Large Data Object Between Ruby Processes
Instance Variables Inheritance
Why Array.Reverse_Each Is Faster Than Array.Reverse.Each
"Cannot Load Such File - Rubygems/Defaults/Operating_System" When Installing Ruby 2.0.0
Bundle Install Tries to Use Cache File
What Exactly Is a Gem Native Extension
Issues with Has_Many :Through, Cache, Touch and Counter_Cache