Creating Rails Form

58 views Asked by At

I'm trying to create a form in rails but I'm getting the following error:

undefined method `[]' for nil:NilClass
Extracted source (around line #1):
1  <%= form_for @url do |f| %>
2    <p>
3      <label>Create an new Short URL now - </label>
4    </p>

new.html.erb

<%= form_for @url do |f| %>
  <p>
    <label>Create an new Short URL now - </label>
  </p>
  <p>
    <%= f.text_field :url %>  
  </p>
  <p>
    <%= f.submit %>
  </p>


<% end %>

home_controller.rb

class HomeController < ApplicationController

  def index

  end

  def about
  end

  def new
    @url = ShortUrl.new
  end    

  def show
    url = params[:id]
    @url = ShortUrl.where(["url = ?", url]).first

    if @url.nil?
      redirect_to home_index_path
    else
      redirect_to @url.full_short_path
    end
  end    
end

short_url.rb

require 'uri'
require 'googl'
class ShortUrl < ActiveRecord::Base
  attr_reader :url, :host, :scheme
  attr_accessor :url_length    
  validates_presence_of  :url, :host, :scheme    
  validates_uniqueness_of :url, :host, :scheme
  VALID_CHARS = (('a'..'z').to_a << (0..9).to_a).flatten

  private 
  attr_accessor :gmail_config
  public

  def initialize
  end

  def setup(url)
    uri = URI.parse(url)
    @host = uri.host
    @scheme = uri.scheme
    @length = url.length/3
    @gmail_config = AML.load_file("#{Rails.root.to_s}/config/gmail_secrets.yml")[Rails.env]
    @url = get_random_string
  end

  def full_short_path
    scheme + host
  end    

  private    

  def get_short_url
    client = Googl.client(@gmail_config['address'], @gmail_config['password'])
    url = client.shorten(full_short_path).short_url
  end    

end
1

There are 1 answers

2
agmcleod On BEST ANSWER

You're sub classing active record. DO NOT overwrite initialize, you need to delete that. AR implements it for you. You can also remove any of the attr_accessor and attr_reader attributes that are database columns. Rails handles this for you.

You'll want to avoid multiple private & public sections as well. Put private/protected sections near the bottom. Here's my re-write of your model:

require 'uri'
require 'googl'
class ShortUrl < ActiveRecord::Base
  attr_reader :url, :host, :scheme
  attr_accessor :gmail_config, :url_length
  validates_presence_of  :url, :host, :scheme
  validates_uniqueness_of :url, :host, :scheme
  VALID_CHARS = (('a'..'z').to_a << (0..9).to_a).flatten

  def setup(url)
    uri = URI.parse(url)
    @host = uri.host
    @scheme = uri.scheme
    @length = url.length/3
    @gmail_config = AML.load_file("#{Rails.root.to_s}/config/gmail_secrets.yml")[Rails.env]
    @url = get_random_string
  end

  def full_short_path
    scheme + host
  end    

private    

  def get_short_url
    client = Googl.client(@gmail_config['address'], @gmail_config['password'])
    url = client.shorten(full_short_path).short_url
  end    

end

Note that you do not want to have an attr_accessor call in private. a) it does nothing, and b) the whole point of it is to make instance variables @url for example public.