login_generator 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/templates/README +27 -50
- data/templates/controller.rb +27 -14
- data/templates/controller_test.rb +20 -22
- data/templates/login_system.rb +5 -5
- data/templates/user.rb +8 -36
- data/templates/user_test.rb +18 -8
- data/templates/user_test.rb.orig +101 -0
- data/templates/view_login.rhtml +2 -2
- metadata +40 -33
data/templates/README
CHANGED
@@ -30,29 +30,29 @@ The model :user is required when you are hitting problems to the degree of
|
|
30
30
|
|
31
31
|
You need a database table corresponding to the User model.
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
33
|
+
mysql syntax:
|
34
|
+
CREATE TABLE users (
|
35
|
+
id int(11) NOT NULL auto_increment,
|
36
|
+
login varchar(80) default NULL,
|
37
|
+
password varchar(40) default NULL,
|
38
|
+
PRIMARY KEY (id)
|
39
|
+
);
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
41
|
+
postgres :
|
42
|
+
CREATE TABLE "users" (
|
43
|
+
"id" SERIAL NOT NULL UNIQUE,
|
44
|
+
"login" VARCHAR(80),
|
45
|
+
"password" VARCHAR,
|
46
|
+
PRIMARY KEY("id")
|
47
|
+
) WITH OIDS;
|
48
|
+
|
49
|
+
|
50
|
+
sqlite:
|
51
|
+
CREATE TABLE 'users' (
|
52
|
+
'id' INTEGER PRIMARY KEY NOT NULL,
|
53
|
+
'user' VARCHAR(80) DEFAULT NULL,
|
54
|
+
'password' VARCHAR(40) DEFAULT NULL
|
55
|
+
);
|
56
56
|
|
57
57
|
Of course your user model can have any amount of extra fields. This is just a
|
58
58
|
starting point
|
@@ -77,43 +77,20 @@ controller which you requested earlier. Simple huh?
|
|
77
77
|
|
78
78
|
How do I...
|
79
79
|
|
80
|
-
... access the user who is currently logged in
|
81
|
-
|
82
|
-
A: You can get the user object from the session using @session['user']
|
83
|
-
Example:
|
84
|
-
Welcome <%%= @session[:user].name %>
|
85
|
-
|
86
80
|
... restrict access to only a few methods?
|
87
81
|
|
88
82
|
A: Use before_filters build in scoping.
|
89
83
|
Example:
|
90
|
-
before_filter :login_required
|
91
|
-
before_filter :login_required
|
84
|
+
before_filter :login_required :only => [:myaccount, :changepassword]
|
85
|
+
before_filter :login_required :except => [:index]
|
92
86
|
|
93
87
|
... check if a user is logged-in in my views?
|
94
88
|
|
95
|
-
A: @session[
|
89
|
+
A: @session['user'] will tell you. Here is an example helper which you can use to make this more pretty:
|
96
90
|
Example:
|
97
91
|
def user?
|
98
|
-
!@session[
|
92
|
+
!@session['user'].nil?
|
99
93
|
end
|
100
94
|
|
101
|
-
... return a user to the page they came from before logging in?
|
102
|
-
|
103
|
-
A: The user will be send back to the last url which called the method "store_location"
|
104
|
-
Example:
|
105
|
-
User was at /articles/show/1, wants to log in.
|
106
|
-
in articles_controller.rb, add store_location to the show function and send the user
|
107
|
-
to the login form.
|
108
|
-
After he logs in he will be send back to /articles/show/1
|
109
|
-
|
110
|
-
|
111
|
-
You can find more help at http://wiki.rubyonrails.com/rails/show/LoginGenerator
|
112
|
-
|
113
|
-
== Changelog
|
114
95
|
|
115
|
-
|
116
|
-
1.0.5 Bugfix in generator code
|
117
|
-
1.0.2 Updated the readme with more tips&tricks
|
118
|
-
1.0.1 Fixed problem in the readme
|
119
|
-
1.0.0 First gem release
|
96
|
+
You can find more help at http://wiki.rubyonrails.com/rails/show/LoginGenerator
|
data/templates/controller.rb
CHANGED
@@ -1,33 +1,46 @@
|
|
1
1
|
class <%= class_name %>Controller < ApplicationController
|
2
|
+
model :user
|
2
3
|
layout 'scaffold'
|
3
4
|
|
4
5
|
def login
|
5
6
|
case @request.method
|
6
7
|
when :post
|
7
|
-
|
8
|
+
if @session['user'] = User.authenticate(@params['user_login'], @params['user_password'])
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
@login = @params[:user_login]
|
10
|
+
flash['notice'] = "Login successful"
|
11
|
+
redirect_back_or_default :action => "welcome"
|
12
|
+
else
|
13
|
+
@login = @params['user_login']
|
14
|
+
@message = "Login unsuccessful"
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
def signup
|
20
|
-
@
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
case @request.method
|
21
|
+
when :post
|
22
|
+
@user = User.new(@params['user'])
|
23
|
+
|
24
|
+
if @user.save
|
25
|
+
@session['user'] = User.authenticate(@user.login, @params['user']['password'])
|
26
|
+
flash['notice'] = "Signup successful"
|
27
|
+
redirect_back_or_default :action => "welcome"
|
28
|
+
end
|
29
|
+
when :get
|
30
|
+
@user = User.new
|
26
31
|
end
|
27
32
|
end
|
28
33
|
|
34
|
+
def delete
|
35
|
+
if @params['id']
|
36
|
+
@user = User.find(@params['id'])
|
37
|
+
@user.destroy
|
38
|
+
end
|
39
|
+
redirect_back_or_default :action => "welcome"
|
40
|
+
end
|
41
|
+
|
29
42
|
def logout
|
30
|
-
@session[
|
43
|
+
@session['user'] = nil
|
31
44
|
end
|
32
45
|
|
33
46
|
def welcome
|
@@ -1,9 +1,6 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../test_helper'
|
2
2
|
require '<%= file_name %>_controller'
|
3
3
|
|
4
|
-
# Set salt to 'change-me' because thats what the fixtures assume.
|
5
|
-
User.salt = 'change-me'
|
6
|
-
|
7
4
|
# Raise errors beyond the default web-based presentation
|
8
5
|
class <%= class_name %>Controller; def rescue_action(e) raise e end; end
|
9
6
|
|
@@ -18,56 +15,57 @@ class <%= class_name %>ControllerTest < Test::Unit::TestCase
|
|
18
15
|
end
|
19
16
|
|
20
17
|
def test_auth_bob
|
21
|
-
@request.session[
|
18
|
+
@request.session['return-to'] = "/bogus/location"
|
22
19
|
|
23
|
-
post :login,
|
24
|
-
assert_session_has
|
20
|
+
post :login, "user_login" => "bob", "user_password" => "test"
|
21
|
+
assert_session_has "user"
|
25
22
|
|
26
|
-
assert_equal @bob, @response.session[
|
23
|
+
assert_equal @bob, @response.session["user"]
|
27
24
|
|
28
25
|
assert_redirect_url "/bogus/location"
|
29
26
|
end
|
30
27
|
|
31
28
|
def test_signup
|
32
|
-
@request.session[
|
29
|
+
@request.session['return-to'] = "/bogus/location"
|
33
30
|
|
34
|
-
post :signup,
|
35
|
-
assert_session_has
|
31
|
+
post :signup, "user" => { "login" => "newbob", "password" => "newpassword", "password_confirmation" => "newpassword" }
|
32
|
+
assert_session_has "user"
|
36
33
|
|
37
34
|
assert_redirect_url "/bogus/location"
|
38
35
|
end
|
39
36
|
|
40
37
|
def test_bad_signup
|
41
|
-
@request.session[
|
38
|
+
@request.session['return-to'] = "/bogus/location"
|
42
39
|
|
43
|
-
post :signup,
|
44
|
-
assert_invalid_column_on_record "user",
|
40
|
+
post :signup, "user" => { "login" => "newbob", "password" => "newpassword", "password_confirmation" => "wrong" }
|
41
|
+
assert_invalid_column_on_record "user", "password"
|
45
42
|
assert_success
|
46
43
|
|
47
|
-
post :signup,
|
48
|
-
assert_invalid_column_on_record "user",
|
44
|
+
post :signup, "user" => { "login" => "yo", "password" => "newpassword", "password_confirmation" => "newpassword" }
|
45
|
+
assert_invalid_column_on_record "user", "login"
|
49
46
|
assert_success
|
50
47
|
|
51
|
-
post :signup,
|
52
|
-
assert_invalid_column_on_record "user", [
|
48
|
+
post :signup, "user" => { "login" => "yo", "password" => "newpassword", "password_confirmation" => "wrong" }
|
49
|
+
assert_invalid_column_on_record "user", ["login", "password"]
|
53
50
|
assert_success
|
54
51
|
end
|
55
52
|
|
56
53
|
def test_invalid_login
|
57
|
-
post :login,
|
54
|
+
post :login, "user_login" => "bob", "user_password" => "not_correct"
|
58
55
|
|
59
|
-
assert_session_has_no
|
56
|
+
assert_session_has_no "user"
|
60
57
|
|
58
|
+
assert_template_has "message"
|
61
59
|
assert_template_has "login"
|
62
60
|
end
|
63
61
|
|
64
62
|
def test_login_logoff
|
65
63
|
|
66
|
-
post :login,
|
67
|
-
assert_session_has
|
64
|
+
post :login, "user_login" => "bob", "user_password" => "test"
|
65
|
+
assert_session_has "user"
|
68
66
|
|
69
67
|
get :logout
|
70
|
-
assert_session_has_no
|
68
|
+
assert_session_has_no "user"
|
71
69
|
|
72
70
|
end
|
73
71
|
|
data/templates/login_system.rb
CHANGED
@@ -46,7 +46,7 @@ module LoginSystem
|
|
46
46
|
return true
|
47
47
|
end
|
48
48
|
|
49
|
-
if @session[
|
49
|
+
if @session['user'] and authorize?(@session['user'])
|
50
50
|
return true
|
51
51
|
end
|
52
52
|
|
@@ -71,16 +71,16 @@ module LoginSystem
|
|
71
71
|
# store current uri in the session.
|
72
72
|
# we can return to this location by calling return_location
|
73
73
|
def store_location
|
74
|
-
@session[
|
74
|
+
@session['return-to'] = @request.request_uri
|
75
75
|
end
|
76
76
|
|
77
77
|
# move to the last store_location call or to the passed default one
|
78
78
|
def redirect_back_or_default(default)
|
79
|
-
if @session[
|
79
|
+
if @session['return-to'].nil?
|
80
80
|
redirect_to default
|
81
81
|
else
|
82
|
-
redirect_to_url @session[
|
83
|
-
@session[
|
82
|
+
redirect_to_url @session['return-to']
|
83
|
+
@session['return-to'] = nil
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
data/templates/user.rb
CHANGED
@@ -3,57 +3,29 @@ require 'digest/sha1'
|
|
3
3
|
# this model expects a certain database layout and its based on the name/login pattern.
|
4
4
|
class User < ActiveRecord::Base
|
5
5
|
|
6
|
-
# Please change the salt to something else,
|
7
|
-
# Every application should use a different one
|
8
|
-
@@salt = 'change-me'
|
9
|
-
cattr_accessor :salt
|
10
|
-
|
11
|
-
# Authenticate a user.
|
12
|
-
#
|
13
|
-
# Example:
|
14
|
-
# @user = User.authenticate('bob', 'bobpass')
|
15
|
-
#
|
16
6
|
def self.authenticate(login, pass)
|
17
7
|
find_first(["login = ? AND password = ?", login, sha1(pass)])
|
18
8
|
end
|
19
|
-
|
20
9
|
|
10
|
+
def change_password(pass)
|
11
|
+
update_attribute "password", self.class.sha1(pass)
|
12
|
+
end
|
13
|
+
|
21
14
|
protected
|
22
15
|
|
23
|
-
# Apply SHA1 encryption to the supplied password.
|
24
|
-
# We will additionally surround the password with a salt
|
25
|
-
# for additional security.
|
26
16
|
def self.sha1(pass)
|
27
|
-
Digest::SHA1.hexdigest("
|
17
|
+
Digest::SHA1.hexdigest("change-me--#{pass}--")
|
28
18
|
end
|
29
19
|
|
30
20
|
before_create :crypt_password
|
31
21
|
|
32
|
-
# Before saving the record to database we will crypt the password
|
33
|
-
# using SHA1.
|
34
|
-
# We never store the actual password in the DB.
|
35
22
|
def crypt_password
|
36
|
-
write_attribute
|
23
|
+
write_attribute("password", self.class.sha1(password))
|
37
24
|
end
|
38
|
-
|
39
|
-
before_update :crypt_unless_empty
|
40
|
-
|
41
|
-
# If the record is updated we will check if the password is empty.
|
42
|
-
# If its empty we assume that the user didn't want to change his
|
43
|
-
# password and just reset it to the old value.
|
44
|
-
def crypt_unless_empty
|
45
|
-
if password.empty?
|
46
|
-
user = self.class.find(self.id)
|
47
|
-
self.password = user.password
|
48
|
-
else
|
49
|
-
write_attribute "password", self.class.sha1(password)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
validates_uniqueness_of :login, :on => :create
|
54
25
|
|
55
|
-
validates_confirmation_of :password
|
56
26
|
validates_length_of :login, :within => 3..40
|
57
27
|
validates_length_of :password, :within => 5..40
|
58
28
|
validates_presence_of :login, :password, :password_confirmation
|
29
|
+
validates_uniqueness_of :login, :on => :create
|
30
|
+
validates_confirmation_of :password, :on => :create
|
59
31
|
end
|
data/templates/user_test.rb
CHANGED
@@ -1,21 +1,30 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../test_helper'
|
2
2
|
|
3
|
-
# Set salt to 'change-me' because thats what the fixtures assume.
|
4
|
-
User.salt = 'change-me'
|
5
|
-
|
6
3
|
class UserTest < Test::Unit::TestCase
|
4
|
+
self.use_instantiated_fixtures = true
|
7
5
|
|
8
6
|
fixtures :users
|
9
7
|
|
10
|
-
def test_auth
|
11
|
-
|
8
|
+
def test_auth
|
12
9
|
assert_equal @bob, User.authenticate("bob", "test")
|
13
10
|
assert_nil User.authenticate("nonbob", "test")
|
14
|
-
|
11
|
+
|
15
12
|
end
|
16
13
|
|
14
|
+
|
15
|
+
def test_passwordchange
|
16
|
+
|
17
|
+
@longbob.change_password("nonbobpasswd")
|
18
|
+
assert_equal @longbob, User.authenticate("longbob", "nonbobpasswd")
|
19
|
+
assert_nil User.authenticate("longbob", "longtest")
|
20
|
+
@longbob.change_password("longtest")
|
21
|
+
assert_equal @longbob, User.authenticate("longbob", "longtest")
|
22
|
+
assert_nil User.authenticate("longbob", "nonbobpasswd")
|
23
|
+
|
24
|
+
end
|
25
|
+
|
17
26
|
def test_disallowed_passwords
|
18
|
-
|
27
|
+
|
19
28
|
u = User.new
|
20
29
|
u.login = "nonbob"
|
21
30
|
|
@@ -84,7 +93,8 @@ class UserTest < Test::Unit::TestCase
|
|
84
93
|
u.password = u.password_confirmation = "bobs_secure_password"
|
85
94
|
assert u.save
|
86
95
|
|
87
|
-
assert_equal '98740ff87bade6d895010bceebbd9f718e7856bb', u.password
|
96
|
+
assert_equal '98740ff87bade6d895010bceebbd9f718e7856bb', u.password
|
97
|
+
|
88
98
|
end
|
89
99
|
|
90
100
|
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class UserTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
fixtures :users
|
6
|
+
|
7
|
+
def test_auth
|
8
|
+
|
9
|
+
assert_equal @bob, User.authenticate("bob", "test")
|
10
|
+
assert_nil User.authenticate("nonbob", "test")
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def test_passwordchange
|
16
|
+
|
17
|
+
@longbob.change_password("nonbobpasswd")
|
18
|
+
assert_equal @longbob, User.authenticate("longbob", "nonbobpasswd")
|
19
|
+
assert_nil User.authenticate("longbob", "longtest")
|
20
|
+
@longbob.change_password("longtest")
|
21
|
+
assert_equal @longbob, User.authenticate("longbob", "longtest")
|
22
|
+
assert_nil User.authenticate("longbob", "nonbobpasswd")
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_disallowed_passwords
|
27
|
+
|
28
|
+
u = User.new
|
29
|
+
u.login = "nonbob"
|
30
|
+
|
31
|
+
u.password = u.password_confirmation = "tiny"
|
32
|
+
assert !u.save
|
33
|
+
assert u.errors.invalid?('password')
|
34
|
+
|
35
|
+
u.password = u.password_confirmation = "hugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehuge"
|
36
|
+
assert !u.save
|
37
|
+
assert u.errors.invalid?('password')
|
38
|
+
|
39
|
+
u.password = u.password_confirmation = ""
|
40
|
+
assert !u.save
|
41
|
+
assert u.errors.invalid?('password')
|
42
|
+
|
43
|
+
u.password = u.password_confirmation = "bobs_secure_password"
|
44
|
+
assert u.save
|
45
|
+
assert u.errors.empty?
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_bad_logins
|
50
|
+
|
51
|
+
u = User.new
|
52
|
+
u.password = u.password_confirmation = "bobs_secure_password"
|
53
|
+
|
54
|
+
u.login = "x"
|
55
|
+
assert !u.save
|
56
|
+
assert u.errors.invalid?('login')
|
57
|
+
|
58
|
+
u.login = "hugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhug"
|
59
|
+
assert !u.save
|
60
|
+
assert u.errors.invalid?('login')
|
61
|
+
|
62
|
+
u.login = ""
|
63
|
+
assert !u.save
|
64
|
+
assert u.errors.invalid?('login')
|
65
|
+
|
66
|
+
u.login = "okbob"
|
67
|
+
assert u.save
|
68
|
+
assert u.errors.empty?
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def test_collision
|
74
|
+
u = User.new
|
75
|
+
u.login = "existingbob"
|
76
|
+
u.password = u.password_confirmation = "bobs_secure_password"
|
77
|
+
assert !u.save
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
def test_create
|
82
|
+
u = User.new
|
83
|
+
u.login = "nonexistingbob"
|
84
|
+
u.password = u.password_confirmation = "bobs_secure_password"
|
85
|
+
|
86
|
+
assert u.save
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_sha1
|
91
|
+
u = User.new
|
92
|
+
u.login = "nonexistingbob"
|
93
|
+
u.password = u.password_confirmation = "bobs_secure_password"
|
94
|
+
assert u.save
|
95
|
+
|
96
|
+
assert_equal '98740ff87bade6d895010bceebbd9f718e7856bb', u.password
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
end
|
data/templates/view_login.rhtml
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
<div title="Account login" id="loginform" class="form">
|
4
4
|
<h3>Please login</h3>
|
5
5
|
|
6
|
-
<%% if @
|
7
|
-
<div id="message"><%%= @
|
6
|
+
<%% if @message %>
|
7
|
+
<div id="message"><%%= @message %></div>
|
8
8
|
<%% end %>
|
9
9
|
|
10
10
|
<label for="user_login">Login:</label><br/>
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.8.
|
2
|
+
rubygems_version: 0.8.11
|
3
3
|
specification_version: 1
|
4
4
|
name: login_generator
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.
|
7
|
-
date:
|
6
|
+
version: 1.2.0
|
7
|
+
date: 2006-04-17 00:00:00 -04:00
|
8
8
|
summary: "[Rails] Login generator."
|
9
9
|
require_paths:
|
10
|
-
|
10
|
+
- .
|
11
11
|
email: tobi@leetsoft.com
|
12
12
|
homepage: http://www.rubyonrails.org/show/Generators
|
13
13
|
rubyforge_project:
|
@@ -18,43 +18,50 @@ bindir: bin
|
|
18
18
|
has_rdoc: false
|
19
19
|
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
20
|
requirements:
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
version: 0.0.0
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
25
24
|
version:
|
26
25
|
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
27
28
|
authors:
|
28
|
-
|
29
|
+
- Tobias Luetke
|
29
30
|
files:
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
31
|
+
- USAGE
|
32
|
+
- login_generator.rb
|
33
|
+
- templates/controller.rb
|
34
|
+
- templates/controller_test.rb
|
35
|
+
- templates/helper.rb
|
36
|
+
- templates/login_system.rb
|
37
|
+
- templates/README
|
38
|
+
- templates/user.rb
|
39
|
+
- templates/user_test.rb
|
40
|
+
- templates/user_test.rb.orig
|
41
|
+
- templates/users.yml
|
42
|
+
- templates/view_login.rhtml
|
43
|
+
- templates/view_logout.rhtml
|
44
|
+
- templates/view_signup.rhtml
|
45
|
+
- templates/view_welcome.rhtml
|
44
46
|
test_files: []
|
47
|
+
|
45
48
|
rdoc_options: []
|
49
|
+
|
46
50
|
extra_rdoc_files: []
|
51
|
+
|
47
52
|
executables: []
|
53
|
+
|
48
54
|
extensions: []
|
55
|
+
|
49
56
|
requirements: []
|
57
|
+
|
50
58
|
dependencies:
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
version:
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: rails
|
61
|
+
version_requirement:
|
62
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 0.10.0
|
67
|
+
version:
|