diff --git a/.gitignore b/.gitignore index d87d4be66..a35fe92d7 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,8 @@ spec/reports test/tmp test/version_tmp tmp + +.idea +*~ +*.swp +*.iml diff --git a/Gemfile b/Gemfile index 4ea25ec84..e6075ba88 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,21 @@ source 'https://rubygems.org' +# Look for $WORKSPACE, otherwise use "workspace" as dev path. +workspace = ENV["WORKSPACE"] || "~/workspace" + + +gem 'pg', '0.14.0' +gem 'jam_db', :path=> "#{workspace}/jam-db/target/ruby_package" +gem 'activerecord', '3.2.7' +gem 'uuidtools', '2.1.2' +gem 'bcrypt-ruby', '3.0.1' + +group :test do + gem "factory_girl" + gem "rspec", "2.10.0" + gem 'spork', '0.9.0' + gem 'database_cleaner', '0.7.0' +end + # Specify your gem's dependencies in jam_ruby.gemspec gemspec diff --git a/README.md b/README.md index 8ebd64687..39a2c2e30 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,8 @@ # JamRuby -TODO: Write a gem description +## Environment +Create development database 'jam_ruby' +`createdb jam_ruby` -## Installation - -Add this line to your application's Gemfile: - - gem 'jam_ruby' - -And then execute: - - $ bundle - -Or install it yourself as: - - $ gem install jam_ruby - -## Usage - -TODO: Write usage instructions here - -## Contributing - -1. Fork it -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Commit your changes (`git commit -am 'Added some feature'`) -4. Push to the branch (`git push origin my-new-feature`) -5. Create new Pull Request +Once you've created your database, migrate it: +`bundle exec jam_ruby up` diff --git a/config/database.yml b/config/database.yml new file mode 100644 index 000000000..322a29d46 --- /dev/null +++ b/config/database.yml @@ -0,0 +1,8 @@ +test: + adapter: postgresql + database: jam_ruby_test + pool: 3 + username: postgres + password: postgres + timeout: 2000 + encoding: unicode \ No newline at end of file diff --git a/lib/jam_ruby.rb b/lib/jam_ruby.rb index 54d06f13e..df2937c53 100644 --- a/lib/jam_ruby.rb +++ b/lib/jam_ruby.rb @@ -1,5 +1,12 @@ +require "pg" +require "active_record" +require "jam_db" +require 'uuidtools' require "jam_ruby/version" +require "jam_ruby/models/extensions/uuid" +require "jam_ruby/models/user" +require "jam_ruby/models/jam_session" module JamRuby - # Your code goes here... + end diff --git a/lib/jam_ruby/dbutil.rb b/lib/jam_ruby/dbutil.rb new file mode 100644 index 000000000..b59c7e2bc --- /dev/null +++ b/lib/jam_ruby/dbutil.rb @@ -0,0 +1,7 @@ +module JamRuby + class DbUtil + def self.create(connection_hash) + + end + end +end \ No newline at end of file diff --git a/lib/jam_ruby/models/extensions/uuid.rb b/lib/jam_ruby/models/extensions/uuid.rb new file mode 100644 index 000000000..406e0c567 --- /dev/null +++ b/lib/jam_ruby/models/extensions/uuid.rb @@ -0,0 +1,13 @@ +module JamRuby + module UUID + extend ActiveSupport::Concern + + included do + before_create :generate_uuid + + def generate_uuid + self.id = UUIDTools::UUID.random_create.to_s + end + end + end +end \ No newline at end of file diff --git a/lib/jam_ruby/models/jam_session.rb b/lib/jam_ruby/models/jam_session.rb new file mode 100644 index 000000000..639f699d7 --- /dev/null +++ b/lib/jam_ruby/models/jam_session.rb @@ -0,0 +1,13 @@ +module JamRuby + class JamSession < ActiveRecord::Base + + include JamRuby::UUID + + # Verifies that the specified user (user_session_id ) can join the jam_sessin_id + # returns true/false + def access?(jam_session_id, user_session_id) + + end + + end +end \ No newline at end of file diff --git a/lib/jam_ruby/models/user.rb b/lib/jam_ruby/models/user.rb new file mode 100644 index 000000000..d219f5bda --- /dev/null +++ b/lib/jam_ruby/models/user.rb @@ -0,0 +1,23 @@ +module JamRuby + class User < ActiveRecord::Base + + attr_accessible :name, :email, :password, :password_confirmation + + has_secure_password + + before_save { |user| user.email = email.downcase } + before_save :create_remember_token + + validates :name, presence: true, length: {maximum: 50} + VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i + validates :email, presence: true, format: {with: VALID_EMAIL_REGEX}, + uniqueness: {case_sensitive: false} + validates :password, length: {minimum: 6} + validates :password_confirmation, presence: true + + private + def create_remember_token + self.remember_token = SecureRandom.urlsafe_base64 + end + end +end \ No newline at end of file diff --git a/spec/factories.rb b/spec/factories.rb new file mode 100644 index 000000000..d71d480d4 --- /dev/null +++ b/spec/factories.rb @@ -0,0 +1,12 @@ +FactoryGirl.define do + factory :user do + sequence(:name) { |n| "Person #{n}" } + sequence(:email) { |n| "person_#{n}@example.com"} + password "foobar" + password_confirmation "foobar" + + factory :admin do + admin true + end + end +end \ No newline at end of file diff --git a/spec/jam_ruby/models/jam_session_spec.rb b/spec/jam_ruby/models/jam_session_spec.rb new file mode 100644 index 000000000..5470417c8 --- /dev/null +++ b/spec/jam_ruby/models/jam_session_spec.rb @@ -0,0 +1,8 @@ +require 'spec_helper' + +describe JamSession do + + it 'can grant access to valid user' do + + end +end \ No newline at end of file diff --git a/spec/jam_ruby/models/user_spec.rb b/spec/jam_ruby/models/user_spec.rb new file mode 100644 index 000000000..4d5103226 --- /dev/null +++ b/spec/jam_ruby/models/user_spec.rb @@ -0,0 +1,138 @@ +require 'spec_helper' + +describe User do + + before do + @user = User.new(name: "Example User", email: "user@example.com", + password: "foobar", password_confirmation: "foobar") + end + + subject { @user } + + it { should respond_to(:name) } + it { should respond_to(:email) } + it { should respond_to(:password_digest) } + it { should respond_to(:password) } + it { should respond_to(:password_confirmation) } + it { should respond_to(:remember_token) } + it { should respond_to(:admin) } + it { should respond_to(:authenticate) } + + it { should be_valid } + it { should_not be_admin } + + describe "accessible attributes" do + it "should not allow access to admin" do + userish = User.new(admin: true, name: "george") + userish.admin.should == false + userish.name.should == "george" + userish.admin = true + userish.admin.should == true + end + end + + describe "with admin attribute set to 'true'" do + before do + @user.save! + @user.toggle!(:admin) + end + + it { should be_admin } + end + + describe "when name is not present" do + before { @user.name = " " } + it { should_not be_valid } + end + + describe "when email is not present" do + before { @user.email = " " } + it { should_not be_valid } + end + + describe "when name is too long" do + before { @user.name = "a" * 51 } + it { should_not be_valid } + end + + describe "when email format is invalid" do + it "should be invalid" do + addresses = %w[user@foo,com user_at_foo.org example.user@foo.] + addresses.each do |invalid_address| + @user.email = invalid_address + @user.should_not be_valid + end + end + end + + describe "when email format is valid" do + it "should be valid" do + addresses = %w[user@foo.COM A_US-ER@f.b.org frst.lst@foo.jp a+b@baz.cn] + addresses.each do |valid_address| + @user.email = valid_address + @user.should be_valid + end + end + end + + describe "when email address is already taken" do + before do + user_with_same_email = @user.dup + user_with_same_email.email = @user.email.upcase + user_with_same_email.save + end + + it { should_not be_valid } + end + + describe "email address with mixed case" do + let(:mixed_case_email) { "Foo@ExAMPle.CoM" } + + it "should be saved as all lower-case" do + @user.email = mixed_case_email + @user.save + @user.reload.email.should == mixed_case_email.downcase + end + end + + describe "when password is not present" do + before { @user.password = @user.password_confirmation = " " } + it { should_not be_valid } + end + + describe "when password doesn't match confirmation" do + before { @user.password_confirmation = "mismatch" } + it { should_not be_valid } + end + + describe "when password confirmation is nil" do + before { @user.password_confirmation = nil } + it { should_not be_valid } + end + + describe "with a password that's too short" do + before { @user.password = @user.password_confirmation = "a" * 5 } + it { should be_invalid } + end + + describe "return value of authenticate method" do + before { @user.save } + let(:found_user) { User.find_by_email(@user.email) } + + describe "with valid password" do + it { should == found_user.authenticate(@user.password) } + end + + describe "with invalid password" do + let(:user_for_invalid_password) { found_user.authenticate("invalid") } + + it { should_not == user_for_invalid_password } + specify { user_for_invalid_password.should be_false } + end + end + + describe "remember token" do + before { @user.save } + its(:remember_token) { should_not be_blank } + end +end \ No newline at end of file diff --git a/spec/spec_db.rb b/spec/spec_db.rb new file mode 100644 index 000000000..5a3a935ee --- /dev/null +++ b/spec/spec_db.rb @@ -0,0 +1,11 @@ +class SpecDb + + TEST_DB_NAME="jam_ruby_test" + + def self.recreate_database + conn = PG::Connection.open("dbname=postgres") + conn.exec("DROP DATABASE IF EXISTS #{TEST_DB_NAME}") + conn.exec("CREATE DATABASE #{TEST_DB_NAME}") + JamDb::Migrator.new.migrate(:dbname => TEST_DB_NAME) + end +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 000000000..490c13840 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,73 @@ + +require 'active_record' +require 'jam_db' +require 'spec_db' + +# recreate test database and migrate it +SpecDb::recreate_database +# initialize ActiveRecord's db connection +ActiveRecord::Base.establish_connection(YAML::load(File.open('config/database.yml'))["test"]) + +require 'jam_ruby' +require 'factory_girl' +require 'rubygems' +require 'spork' +require 'database_cleaner' + +include JamRuby + + +#uncomment the following line to use spork with the debugger +#require 'spork/ext/ruby-debug' + +Spork.prefork do + # Loading more in this block will cause your tests to run faster. However, + # if you change any configuration or code from libraries loaded here, you'll + # need to restart spork for it take effect. +# This file is copied to spec/ when you run 'rails generate rspec:install' + #ENV["RAILS_ENV"] ||= 'test' + #require File.expand_path("../../config/environment", __FILE__) + require 'rspec/autorun' + #require 'rspec/rails' +# This file was generated by the `rspec --init` command. Conventionally, all +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. +# Require this file using `require "spec_helper"` to ensure that it is only +# loaded once. +# +# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration + RSpec.configure do |config| + config.treat_symbols_as_metadata_keys_with_true_values = true + config.run_all_when_everything_filtered = true + config.filter_run :focus + + config.before(:suite) do + DatabaseCleaner.strategy = :transaction + DatabaseCleaner.clean_with(:truncation) + end + + config.before(:each) do + DatabaseCleaner.start + end + + config.after(:each) do + DatabaseCleaner.clean + end + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + #config.use_transactional_fixtures = true + + # Run specs in random order to surface order dependencies. If you find an + # order dependency and want to debug it, you can fix the order by providing + # the seed, which is printed after each run. + # --seed 1234 + config.order = 'random' + end +end + + +Spork.each_run do + # This code will be run each time you run your specs. + +end \ No newline at end of file