EzDevInfo.com

hashids.js

A small JavaScript class to generate YouTube-like hashids from one or many numbers. This is a client-side version of Node.js version. JavaScript - Hashids generate short unique ids from integers. use in url shortening or as unique ids.

How do I implement hashids in ruby on rails

I will go ahead and apologize upfront as I am new to ruby and rails and I cannot for the life of me figure out how to implement using hashids in my project. The project is a simple image host. I have it already working using Base58 to encode the sql ID and then decode it in the controller. However I wanted to make the URLs more random hence switching to hashids.

I have placed the hashids.rb file in my lib directory from here: https://github.com/peterhellberg/hashids.rb

Now some of the confusion starts here. Do I need to initialize hashids on every page that uses hashids.encode and hashids.decode via

hashids = Hashids.new("mysalt")

I found this post (http://zogovic.com/post/75234760043/youtube-like-ids-for-your-activerecord-models) which leads me to believe I can put it into an initializer however after doing that I am still getting NameError (undefined local variable or method `hashids' for ImageManager:Class)

so in my ImageManager.rb class I have

require 'hashids'

class ImageManager
class << self
def save_image(imgpath, name)

  mime = %x(/usr/bin/exiftool -MIMEType #{imgpath})[34..-1].rstrip
  if mime.nil? || !VALID_MIME.include?(mime)
    return { status: 'failure', message: "#{name} uses an invalid format." }
  end

  hash = Digest::MD5.file(imgpath).hexdigest
  image = Image.find_by_imghash(hash)

  if image.nil?
    image = Image.new
    image.mimetype = mime
    image.imghash = hash
    unless image.save!
      return { status: 'failure', message: "Failed to save #{name}." }
    end

    unless File.directory?(Rails.root.join('uploads'))
      Dir.mkdir(Rails.root.join('uploads'))
    end
    #File.open(Rails.root.join('uploads', "#{Base58.encode(image.id)}.png"), 'wb') { |f| f.write(File.open(imgpath, 'rb').read) }
    File.open(Rails.root.join('uploads', "#{hashids.encode(image.id)}.png"), 'wb') { |f| f.write(File.open(imgpath, 'rb').read) }
  end

  link = ImageLink.new
  link.image = image
  link.save

#return { status: 'success', message: Base58.encode(link.id) }
return { status: 'success', message: hashids.encode(link.id) }
end

private

    VALID_MIME = %w(image/png image/jpeg image/gif)
  end
end

And in my controller I have:

require 'hashids'

class MainController < ApplicationController
MAX_FILE_SIZE = 10 * 1024 * 1024
MAX_CACHE_SIZE = 128 * 1024 * 1024

@links = Hash.new
@files = Hash.new
@tstamps = Hash.new
@sizes = Hash.new
@cache_size = 0

class << self
  attr_accessor :links
  attr_accessor :files
  attr_accessor :tstamps
  attr_accessor :sizes
  attr_accessor :cache_size
  attr_accessor :hashids
end

def index
end

def transparency
end

def image
  #@imglist = params[:id].split(',').map{ |id| ImageLink.find(Base58.decode(id)) }
  @imglist = params[:id].split(',').map{ |id| ImageLink.find(hashids.decode(id)) }
end

def image_direct
  #linkid = Base58.decode(params[:id])
  linkid = hashids.decode(params[:id])

  file =
    if Rails.env.production?
      puts "#{Base58.encode(ImageLink.find(linkid).image.id)}.png"
      File.open(Rails.root.join('uploads', "#{Base58.encode(ImageLink.find(linkid).image.id)}.png"), 'rb') { |f| f.read }
    else
      puts "#{hashids.encode(ImageLink.find(linkid).image.id)}.png"
      File.open(Rails.root.join('uploads', "#{hashids.encode(ImageLink.find(linkid).image.id)}.png"), 'rb') { |f| f.read }
    end

  send_data(file, type: ImageLink.find(linkid).image.mimetype, disposition: 'inline')
end

def upload
  imgparam = params[:image]

  if imgparam.is_a?(String)
    name = File.basename(imgparam)
    imgpath = save_to_tempfile(imgparam).path
  else
    name = imgparam.original_filename
    imgpath = imgparam.tempfile.path
  end

  File.chmod(0666, imgpath)
  %x(/usr/bin/exiftool -all= -overwrite_original #{imgpath})
  logger.debug %x(which exiftool)
  render json: ImageManager.save_image(imgpath, name)
end

private

  def save_to_tempfile(url)
  uri = URI.parse(url)

  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = uri.scheme == 'https'
  http.start do
    resp = http.get(uri.path)
    file = Tempfile.new('urlupload', Dir.tmpdir, :encoding => 'ascii-8bit')
    file.write(resp.body)
    file.flush
    return file
  end
end
end

Then in my image.html.erb view I have this:

<%
   @imglist.each_with_index { |link, i|
   id = hashids.encode(link.id)
   ext = link.image.mimetype.split('/')[1]
   if ext == 'jpeg'
     ext = 'jpg'
   end
   puts id + '.' + ext
%>

Now if I add

hashids = Hashids.new("mysalt")

in ImageManager.rb main_controller.rb and in my image.html.erb I am getting this error:

ActionView::Template::Error (undefined method `id' for #<Array:0x000000062f69c0>)

So all in all implementing hashids.encode/decode is not as easy as implementing Base58.encode/decode and I am confused on how to get it working... Any help would be greatly appreciated.


Source: (StackOverflow)

Use Hashids library to hash ids on Laravel eloquent collection

I'm grabbing a set of tasks from a database as an eloquent collection, then I'm sending the collection to my view where I do a foreach. No problems here. Except, I need to reference the task id in my view (url action, etc.). But I obviously don't want this in the source, so I'm using this library to hash the id. But doing this in the view seems wrong.

Is there any way to hash the id in the model or controller?

Here's how I'm calling the collection in my controller:

$tasks = Auth::user()->tasks()->orderBy('created_at', 'desc')->get();

This is how I'm currently hashing the id in my view:

<a rel='nofollow' href="{{ route('tasks.markascompleted', Hashids::encode($task->id)) }}">

Any help?


Source: (StackOverflow)

Advertisements

MarshalJSON error , invalid character "g" after top-level

got a problem... I can't understand it

I made a custom type for my IDs

type ID uint

func (id ID) MarshalJSON() ([]byte, error) {
    e, _ := HashIDs.Encode([]int{int(id)})
    fmt.Println(e) /// 34gj
    return []byte(e), nil
}

func (id *ID) Scan(value interface{}) error {
    *id = ID(value.(int64))
    return nil
}

I use HashIDs package to encode my ids so that user wont be able to read them on client side. but I'm getting this error:

json: error calling MarshalJSON for type types.ID: invalid character 'g' after top-level value


Source: (StackOverflow)

Laravel 5 Route binding and Hashid

I am using Hashid to hide the id of a resource in Laravel 5.

Here is the route bind in the routes file:

Route::bind('schedule', function($value, $route)
{
    $hashids = new Hashids\Hashids(env('APP_KEY'),8);
    if( isset($hashids->decode($value)[0]) )
    {
        $id = $hashids->decode($value)[0];
        return App\Schedule::findOrFail($id);
    }
    App::abort(404);
});

And in the model:

public function getRouteKey()
{
    $hashids = new \Hashids\Hashids(env('APP_KEY'),8);
    return $hashids->encode($this->getKey());
}

Now this works fine the resource displays perfectly and the ID is hashed. BUT when I go to my create route, it 404's - if I remove App::abort(404) the create route goes to the resource 'show' view without any data...

Here is the Create route:

Route::get('schedules/create', [
  'uses' => 'SchedulesController@create',
  'as' => 'schedules.create'
]);

The Show route:

Route::get('schedules/{schedule}', [
  'uses' => 'Schedules Controller@show',
  'as' => 'schedules.show'
]);

I am also binding the model to the route:

Route::model('schedule', 'App\Schedule');

Any ideas why my create view is not showing correctly? The index view displays fine.


Source: (StackOverflow)

Using Hashids in a for loop jQuery

I'm trying to use the hashids plugin to hash ticket_id within a for loop.

for (var i = 0; i < result.length; i++) {
    var hashids = new Hashids("", 5);
    var id = hashids.encode(result[i].ticket_id);
    console.log(hashids);
    [...]

    html += '<tr class="ticketClick" data-url="' + baseURL + id>' [...]
}

HTML for a table is dynamically generated based on the result passed by an ajax call. When the table row is clicked I redirect to the url in the data-url attribute.

The problem is that hashids doesn't run and therefore id isn't being appended to the url.

The console log of hashids produces:

Hashids {version: "1.0.2", minAlphabetLength: 16, sepDiv: 3.5, guardDiv: 12, errorAlphabetLength: "error: alphabet must contain at least X unique characters"…}

I've searched for the error and didn't find anything...

What I find strange is that if I pass an integer directly into the hashids method like:

var id = hashids.encode(20);

The encode works and returns the expected hash.

A console.log of result[i].ticket_id returns the expected integer, so the for loop is doing it's job properly. Declaring new Hashids() outside the for loop doesn't seem to make a difference. So I'm not sure what's going wrong here. Any suggestions?


Source: (StackOverflow)