qa 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/app/controllers/qa/terms_controller.rb +31 -24
  3. data/config/routes.rb +2 -0
  4. data/lib/qa/authorities.rb +3 -1
  5. data/lib/qa/authorities/base.rb +5 -32
  6. data/lib/qa/authorities/lcsh.rb +21 -26
  7. data/lib/qa/authorities/loc.rb +124 -164
  8. data/lib/qa/authorities/local.rb +22 -57
  9. data/lib/qa/authorities/local/subauthority.rb +61 -0
  10. data/lib/qa/authorities/mesh.rb +13 -6
  11. data/lib/qa/authorities/oclcts.rb +18 -29
  12. data/lib/qa/authorities/tgnlang.rb +38 -23
  13. data/lib/qa/authorities/web_service_base.rb +20 -0
  14. data/lib/qa/version.rb +1 -1
  15. data/spec/controllers/terms_controller_spec.rb +6 -2
  16. data/spec/fixtures/authorities/authority_B.yml +7 -7
  17. data/spec/fixtures/authorities/authority_D.yml +4 -0
  18. data/spec/internal/Gemfile +2 -2
  19. data/spec/internal/Gemfile.lock +42 -39
  20. data/spec/internal/config/initializers/secret_token.rb +1 -1
  21. data/spec/internal/config/routes.rb +1 -1
  22. data/spec/internal/db/development.sqlite3 +0 -0
  23. data/spec/internal/db/migrate/{20130930151844_create_qa_subject_mesh_terms.qa.rb → 20131106203101_create_qa_subject_mesh_terms.qa.rb} +0 -0
  24. data/spec/internal/db/migrate/{20130930151845_create_qa_mesh_tree.qa.rb → 20131106203102_create_qa_mesh_tree.qa.rb} +0 -0
  25. data/spec/internal/db/migrate/{20130930151846_add_term_lower_to_qa_subject_mesh_terms.qa.rb → 20131106203103_add_term_lower_to_qa_subject_mesh_terms.qa.rb} +0 -0
  26. data/spec/internal/db/schema.rb +1 -1
  27. data/spec/internal/db/test.sqlite3 +0 -0
  28. data/spec/internal/log/development.log +6436 -79
  29. data/spec/lib/authorities_lcsh_spec.rb +30 -41
  30. data/spec/lib/authorities_loc_spec.rb +4 -3
  31. data/spec/lib/authorities_local_spec.rb +63 -27
  32. data/spec/lib/authorities_mesh_spec.rb +8 -2
  33. data/spec/lib/authorities_oclcts_spec.rb +6 -5
  34. data/spec/lib/authorities_tgnlang_spec.rb +6 -9
  35. data/spec/spec_helper.rb +7 -0
  36. metadata +49 -55
@@ -1,69 +1,34 @@
1
1
  module Qa::Authorities
2
+
2
3
  class Local < Qa::Authorities::Base
3
-
4
- attr_accessor :response
5
-
6
- def initialize(q, sub_authority)
7
- begin
8
- sub_authority_hash = YAML.load(File.read(File.join(Qa::Authorities::Local.sub_authorities_path, "#{sub_authority}.yml")))
9
- rescue
10
- sub_authority_hash = {}
11
- end
12
- @terms = normalize_terms(sub_authority_hash.fetch(:terms, []))
13
- if q.blank?
14
- self.response = @terms
15
- else
16
- sub_terms = []
17
- @terms.each { |term| sub_terms << term if term[:term].downcase.start_with?(q.downcase) }
18
- self.response = sub_terms
4
+
5
+ class << self
6
+ def sub_authority(name)
7
+ @sub_authorities ||= {}
8
+ raise ArgumentError, "Invalid sub-authority '#{name}'" unless Subauthority.names.include?(name)
9
+ @sub_authorities[name] ||= Subauthority.new(name)
19
10
  end
20
- end
21
11
 
22
- def normalize_terms(terms)
23
- normalized_terms = []
24
- terms.each do |term|
25
- if term.is_a? String
26
- normalized_terms << { :id => term, :term => term }
27
- else
28
- term[:id] = term[:id] || term[:term]
29
- normalized_terms << term
30
- end
12
+ def sub_authorities
13
+ Subauthority.names
31
14
  end
32
- normalized_terms
33
- end
34
15
 
35
- def parse_authority_response
36
- parsed_response = []
37
- self.response.each do |res|
38
- parsed_response << { :id => res[:id], :label => res[:term] }
16
+ def terms(sub_authority)
17
+ sub_authority(sub_authority).terms
39
18
  end
40
- self.response = parsed_response
41
19
  end
42
-
43
- def get_full_record(id)
44
- target_term = {}
45
- @terms.each do |term|
46
- if term[:id] == id
47
- target_term = term
48
- end
49
- end
50
- target_term.to_json
20
+
21
+ def search(q, sub_authority)
22
+ Local.sub_authority(sub_authority).search(q)
51
23
  end
52
-
53
- def self.sub_authorities_path
54
- config_path = AUTHORITIES_CONFIG[:local_path]
55
- if config_path.starts_with?(File::Separator)
56
- config_path
57
- else
58
- File.join(Rails.root, config_path)
24
+
25
+ def get_full_record(id, sub_authority)
26
+ terms = Local.sub_authority(sub_authority).terms
27
+ terms.each do |term|
28
+ return term if term[:id] == id
59
29
  end
30
+ return {}
60
31
  end
61
-
62
- def self.sub_authorities
63
- sub_auths = []
64
- Dir.foreach(Qa::Authorities::Local.sub_authorities_path) { |file| sub_auths << File.basename(file, File.extname(file)) }
65
- sub_auths
66
- end
67
-
32
+
68
33
  end
69
- end
34
+ end
@@ -0,0 +1,61 @@
1
+ module Qa::Authorities
2
+ # This is really just a sub-authority for Local
3
+ class Subauthority
4
+ attr_reader :name
5
+ def initialize(name)
6
+ @name = name
7
+ end
8
+
9
+ def terms
10
+ @terms ||= load_sub_authority_terms
11
+ end
12
+
13
+ def search(q)
14
+ r = q.blank? ? terms : terms.select { |term| /\b#{q.downcase}/.match(term[:term].downcase) }
15
+ r.map do |res|
16
+ { :id => res[:id], :label => res[:term] }.with_indifferent_access
17
+ end
18
+ end
19
+
20
+ class << self
21
+ def sub_authorities_path
22
+ config_path = AUTHORITIES_CONFIG[:local_path]
23
+ if config_path.starts_with?(File::Separator)
24
+ return config_path
25
+ end
26
+ File.join(Rails.root, config_path)
27
+ end
28
+
29
+ def names
30
+ @sub_auth_names ||=
31
+ begin
32
+ sub_auths = []
33
+ Dir.foreach(sub_authorities_path) { |file| sub_auths << File.basename(file, File.extname(file)) }
34
+ sub_auths
35
+ end
36
+ end
37
+ end
38
+
39
+ private
40
+ def load_sub_authority_terms
41
+ sub_authority_hash = YAML.load(File.read(sub_authority_filename))
42
+ terms = sub_authority_hash.with_indifferent_access.fetch(:terms, [])
43
+ normalize_terms(terms)
44
+ end
45
+
46
+ def sub_authority_filename
47
+ File.join(self.class.sub_authorities_path, "#{name}.yml")
48
+ end
49
+
50
+ def normalize_terms(terms)
51
+ terms.map do |term|
52
+ if term.is_a? String
53
+ { :id => term, :term => term }.with_indifferent_access
54
+ else
55
+ term[:id] ||= term[:term]
56
+ term
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,15 +1,22 @@
1
1
  module Qa::Authorities
2
2
  class Mesh
3
3
 
4
- def initialize(q, sub_authority=nil)
4
+ def results
5
+ @results ||= begin
6
+ r = Qa::SubjectMeshTerm.where('term_lower LIKE ?', "#{@q}%").limit(10)
7
+ r.map { |t| {id: t.term_id, label: t.term} }
8
+ end
9
+ end
10
+
11
+ def search(q, sub_authority=nil)
5
12
  @q = q
6
13
  end
7
14
 
8
- def results
15
+ def get_full_record(id)
9
16
  @results ||= begin
10
- r = SubjectMeshTerm.where('term_lower LIKE ?', "#{@q}%").limit(10)
11
- r.map { |t| {id: t.term_id, label: t.term} }
12
- end.to_json
17
+ r = Qa::SubjectMeshTerm.where(term_id: id).limit(1).first
18
+ r.nil? ? nil : {id: r.term_id, label: r.term, synonyms: r.synonyms}
19
+ end
13
20
  end
14
21
 
15
22
  # satisfy TermsController
@@ -17,4 +24,4 @@ module Qa::Authorities
17
24
  end
18
25
 
19
26
  end
20
- end
27
+ end
@@ -8,56 +8,45 @@ module Qa::Authorities
8
8
 
9
9
  attr_accessor :sub_authority
10
10
 
11
- def initialize(q, sub_authority='')
12
- self.sub_authority = sub_authority
13
- self.query_url = SRU_SERVER_CONFIG["url-pattern"]["prefix-query"].gsub(/\{query\}/, q).gsub(/\{authority\-id\}/, sub_authority)
14
- self.raw_response = Nokogiri::XML(open(self.query_url))
11
+ def initialize
15
12
  end
16
13
 
17
14
  def self.authority_valid?(sub_authority)
18
- sub_authorities.include?(sub_authority)
15
+ self.sub_authorities.include?(sub_authority)
19
16
  end
20
17
 
21
18
  def self.sub_authorities
22
- a = []
23
- SRU_SERVER_CONFIG["authorities"].each do | sub_authority |
24
- a.append(sub_authority[0])
25
- end
26
- a
19
+ @sub_authorities ||= SRU_SERVER_CONFIG["authorities"].map { |sub_authority| sub_authority[0] }
27
20
  end
28
21
 
29
- def parse_authority_response
22
+ def search(q, sub_authority=nil)
23
+ raw_response = get_raw_response("prefix-query", q, sub_authority)
30
24
  r = Array.new
31
- self.raw_response.xpath('sru:searchRetrieveResponse/sru:records/sru:record/sru:recordData', 'sru' => 'http://www.loc.gov/zing/srw/').each do |record|
25
+ raw_response.xpath('sru:searchRetrieveResponse/sru:records/sru:record/sru:recordData', 'sru' => 'http://www.loc.gov/zing/srw/').each do |record|
32
26
  r.append({"id" => record.xpath('Zthes/term/termId').first.content, "label" => record.xpath('Zthes/term/termName').first.content})
33
27
  end
34
- self.response = r
28
+ r
35
29
  end
36
30
 
37
- def get_full_record(id)
38
- unless self.raw_response.xpath("sru:searchRetrieveResponse/sru:records/sru:record/sru:recordData/Zthes/term[termId='" + id + "']", 'sru' => 'http://www.loc.gov/zing/srw/').blank?
39
- parse_full_record(self.raw_response, id)
40
- else
41
- url = SRU_SERVER_CONFIG["url-pattern"]["id-lookup"].gsub(/\{id\}/, id).gsub(/\{authority\-id\}/, self.sub_authority)
42
- parse_full_record(Nokogiri::XML(open(url)), id)
43
- end
44
-
31
+ def get_full_record(id, sub_authority)
32
+ raw_response = get_raw_response("id-lookup", id, sub_authority)
33
+ parse_full_record(raw_response, id)
45
34
  end
46
-
35
+
47
36
  def parse_full_record(raw_xml, id)
48
37
  a = {}
49
- zthes_record = raw_xml.xpath("sru:searchRetrieveResponse/sru:records/sru:record/sru:recordData/Zthes/term[termId='" + id + "']", 'sru' => 'http://www.loc.gov/zing/srw/');
50
- zthes_record.children.each do | child |
38
+ zthes_record = raw_xml.xpath("sru:searchRetrieveResponse/sru:records/sru:record/sru:recordData/Zthes/term[termId='#{id}']", 'sru' => 'http://www.loc.gov/zing/srw/')
39
+ zthes_record.children.each do |child|
51
40
  if (child.is_a? Nokogiri::XML::Element) && (!child.children.nil?) && (child.children.size == 1) && (child.children.first.is_a? Nokogiri::XML::Text)
52
- a[child.name] = child.children.first.to_s;
41
+ a[child.name] = child.children.first.to_s
53
42
  end
54
43
  end
55
- a;
44
+ a
56
45
  end
57
46
 
58
- def results
59
- self.response.to_json
47
+ def get_raw_response(query_type, id, sub_authority)
48
+ query_url = SRU_SERVER_CONFIG["url-pattern"][query_type].gsub("{query}", id).gsub("{id}", id).gsub("{authority-id}", sub_authority)
49
+ Nokogiri::XML(open(query_url))
60
50
  end
61
-
62
51
  end
63
52
  end
@@ -1,40 +1,55 @@
1
1
  require 'nokogiri'
2
- require 'json'
3
2
 
4
3
  module Qa::Authorities
5
4
  class Tgnlang
6
- attr_accessor :response, :raw_response
7
- def initialize(q,sub_authority='')
8
- self.raw_response = getTgnLang(q)
5
+ attr_accessor :response
6
+
7
+ def initialize
8
+ end
9
+
10
+ def search(q, sub_authority='')
11
+ self.response = getTgnLang(q)
9
12
  end
10
13
 
11
14
  def getTgnLang(q)
12
- str = File.expand_path("../../data/TGN_LANGUAGES.xml", __FILE__)
13
- doc = Nokogiri::XML(File.open(str))
14
- size = doc.css("Language_Name").size
15
- i=0
16
- lang_array = Array.new
17
- while i < size do
18
- lang_hash = Hash.new
19
- lang_hash["id"] = doc.css("Language_Code")[i].text
20
- lang_hash["label"] = doc.css("Language_Name")[i].text
21
- lang_array.push(lang_hash)
22
- i+=1
23
- end
24
- obj = Array.new
25
- lang_array.each do |h|
26
- if h["label"].downcase.start_with?(q.downcase)
15
+ obj = Array.new
16
+ Tgnlang.languages.each do |h|
17
+ if h["label"].downcase.start_with?(q.downcase)
27
18
  obj.push(h)
28
19
  end
29
20
  end
30
- obj.to_json
21
+ obj
22
+ end
23
+
24
+ def self.languages
25
+ @languages ||=
26
+ begin
27
+ language_filename = File.expand_path("../../data/TGN_LANGUAGES.xml", __FILE__)
28
+ lang_array = []
29
+ File.open(language_filename) do |f|
30
+ doc = Nokogiri::XML(f)
31
+ lang_array = doc.css("Language").map do |lang|
32
+ id = lang.css("Language_Code").first.text
33
+ label = lang.css("Language_Name").first.text
34
+ {"id" => id, "label" => label}
35
+ end
36
+ end
37
+ lang_array
38
+ end
31
39
  end
32
40
 
33
41
  def results
34
- self.raw_response
42
+ self.response
35
43
  end
36
- def parse_authority_response
37
- self.raw_response
44
+
45
+ def get_full_record(id, sub_authority)
46
+ id = id.downcase
47
+ Tgnlang.languages.each do |h|
48
+ if h["label"].downcase == id
49
+ return h
50
+ end
51
+ end
52
+ return {}
38
53
  end
39
54
  end
40
55
  end
@@ -0,0 +1,20 @@
1
+ require 'curl'
2
+ require 'rest_client'
3
+
4
+ module Qa::Authorities
5
+ class WebServiceBase
6
+ attr_accessor :response, :raw_response
7
+
8
+ # mix-in to retreive and parse JSON content from the web
9
+ def get_json(url)
10
+ r = RestClient.get url, {accept: :json}
11
+ self.response = JSON.parse(r)
12
+ end
13
+
14
+ # This method should be removed
15
+ # use #response instead
16
+ def results
17
+ self.response
18
+ end
19
+ end
20
+ end
@@ -1,3 +1,3 @@
1
1
  module Qa
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -14,7 +14,7 @@ describe Qa::TermsController do
14
14
  get :index, { :vocab => nil}
15
15
  response.code.should == "400"
16
16
  end
17
-
17
+
18
18
  it "should return 400 if no query is specified" do
19
19
  get :index, { :q => nil}
20
20
  response.code.should == "400"
@@ -65,6 +65,10 @@ describe Qa::TermsController do
65
65
  end
66
66
 
67
67
  end
68
-
68
+
69
+ describe "#show" do
70
+ it "the path resolves"
71
+ end
72
+
69
73
  end
70
74
  end
@@ -1,7 +1,7 @@
1
- :terms:
2
- - :id:
3
- :term: Term B1
4
- - :id:
5
- :term: Term B2
6
- - :id:
7
- :term: Term B3
1
+ terms:
2
+ - id:
3
+ term: Term B1
4
+ - id:
5
+ term: Term B2
6
+ - id:
7
+ term: Term B3
@@ -0,0 +1,4 @@
1
+ # this file is purposfully malformed so it should raise an error.
2
+ :terms:
3
+ -:bar: baz
4
+ :biz: bzzz
@@ -1,7 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
4
- gem 'rails', '4.0.0'
4
+ gem 'rails', '4.0.1'
5
5
 
6
6
  # Use sqlite3 as the database for Active Record
7
7
  gem 'sqlite3'
@@ -33,7 +33,7 @@ group :doc do
33
33
  end
34
34
 
35
35
  # Use ActiveModel has_secure_password
36
- # gem 'bcrypt-ruby', '~> 3.0.0'
36
+ # gem 'bcrypt-ruby', '~> 3.1.2'
37
37
 
38
38
  # Use unicorn as the app server
39
39
  # gem 'unicorn'
@@ -6,95 +6,98 @@ PATH
6
6
  curb
7
7
  nokogiri (~> 1.6.0)
8
8
  rails (~> 4.0.0)
9
+ rest-client
9
10
 
10
11
  GEM
11
12
  remote: https://rubygems.org/
12
13
  specs:
13
- actionmailer (4.0.0)
14
- actionpack (= 4.0.0)
15
- mail (~> 2.5.3)
16
- actionpack (4.0.0)
17
- activesupport (= 4.0.0)
14
+ actionmailer (4.0.1)
15
+ actionpack (= 4.0.1)
16
+ mail (~> 2.5.4)
17
+ actionpack (4.0.1)
18
+ activesupport (= 4.0.1)
18
19
  builder (~> 3.1.0)
19
20
  erubis (~> 2.7.0)
20
21
  rack (~> 1.5.2)
21
22
  rack-test (~> 0.6.2)
22
- activemodel (4.0.0)
23
- activesupport (= 4.0.0)
23
+ activemodel (4.0.1)
24
+ activesupport (= 4.0.1)
24
25
  builder (~> 3.1.0)
25
- activerecord (4.0.0)
26
- activemodel (= 4.0.0)
26
+ activerecord (4.0.1)
27
+ activemodel (= 4.0.1)
27
28
  activerecord-deprecated_finders (~> 1.0.2)
28
- activesupport (= 4.0.0)
29
+ activesupport (= 4.0.1)
29
30
  arel (~> 4.0.0)
30
31
  activerecord-deprecated_finders (1.0.3)
31
32
  activerecord-import (0.4.1)
32
33
  activerecord (>= 3.0)
33
- activesupport (4.0.0)
34
+ activesupport (4.0.1)
34
35
  i18n (~> 0.6, >= 0.6.4)
35
36
  minitest (~> 4.2)
36
37
  multi_json (~> 1.3)
37
38
  thread_safe (~> 0.1)
38
39
  tzinfo (~> 0.3.37)
39
40
  addressable (2.3.5)
40
- arel (4.0.0)
41
+ arel (4.0.1)
41
42
  atomic (1.1.14)
42
43
  builder (3.1.4)
43
- coffee-rails (4.0.0)
44
+ coffee-rails (4.0.1)
44
45
  coffee-script (>= 2.2.0)
45
- railties (>= 4.0.0.beta, < 5.0)
46
+ railties (>= 4.0.0, < 5.0)
46
47
  coffee-script (2.2.0)
47
48
  coffee-script-source
48
49
  execjs
49
50
  coffee-script-source (1.6.3)
50
51
  crack (0.4.1)
51
52
  safe_yaml (~> 0.9.0)
52
- curb (0.8.4)
53
+ curb (0.8.5)
53
54
  diff-lcs (1.2.4)
54
55
  erubis (2.7.0)
55
56
  execjs (2.0.2)
56
57
  hike (1.2.3)
57
58
  i18n (0.6.5)
58
- jbuilder (1.5.1)
59
+ jbuilder (1.5.2)
59
60
  activesupport (>= 3.0.0)
60
61
  multi_json (>= 1.2.0)
61
62
  jquery-rails (3.0.4)
62
63
  railties (>= 3.0, < 5.0)
63
64
  thor (>= 0.14, < 2.0)
64
- json (1.8.0)
65
+ json (1.8.1)
65
66
  mail (2.5.4)
66
67
  mime-types (~> 1.16)
67
68
  treetop (~> 1.4.8)
68
69
  mime-types (1.25)
69
- mini_portile (0.5.1)
70
+ mini_portile (0.5.2)
70
71
  minitest (4.7.5)
71
- multi_json (1.8.0)
72
+ multi_json (1.8.2)
72
73
  nokogiri (1.6.0)
73
74
  mini_portile (~> 0.5.0)
74
75
  polyglot (0.3.3)
75
76
  rack (1.5.2)
76
77
  rack-test (0.6.2)
77
78
  rack (>= 1.0)
78
- rails (4.0.0)
79
- actionmailer (= 4.0.0)
80
- actionpack (= 4.0.0)
81
- activerecord (= 4.0.0)
82
- activesupport (= 4.0.0)
79
+ rails (4.0.1)
80
+ actionmailer (= 4.0.1)
81
+ actionpack (= 4.0.1)
82
+ activerecord (= 4.0.1)
83
+ activesupport (= 4.0.1)
83
84
  bundler (>= 1.3.0, < 2.0)
84
- railties (= 4.0.0)
85
+ railties (= 4.0.1)
85
86
  sprockets-rails (~> 2.0.0)
86
- railties (4.0.0)
87
- actionpack (= 4.0.0)
88
- activesupport (= 4.0.0)
87
+ railties (4.0.1)
88
+ actionpack (= 4.0.1)
89
+ activesupport (= 4.0.1)
89
90
  rake (>= 0.8.7)
90
91
  thor (>= 0.18.1, < 2.0)
91
92
  rake (10.1.0)
92
93
  rdoc (3.12.2)
93
94
  json (~> 1.4)
94
- rspec-core (2.14.5)
95
+ rest-client (1.6.7)
96
+ mime-types (>= 1.16)
97
+ rspec-core (2.14.7)
95
98
  rspec-expectations (2.14.3)
96
99
  diff-lcs (>= 1.1.3, < 2.0)
97
- rspec-mocks (2.14.3)
100
+ rspec-mocks (2.14.4)
98
101
  rspec-rails (2.14.0)
99
102
  actionpack (>= 3.0)
100
103
  activesupport (>= 3.0)
@@ -103,9 +106,9 @@ GEM
103
106
  rspec-expectations (~> 2.14.0)
104
107
  rspec-mocks (~> 2.14.0)
105
108
  safe_yaml (0.9.7)
106
- sass (3.2.11)
107
- sass-rails (4.0.0)
108
- railties (>= 4.0.0.beta, < 5.0)
109
+ sass (3.2.12)
110
+ sass-rails (4.0.1)
111
+ railties (>= 4.0.0, < 5.0)
109
112
  sass (>= 3.1.10)
110
113
  sprockets-rails (~> 2.0.0)
111
114
  sdoc (0.3.20)
@@ -116,7 +119,7 @@ GEM
116
119
  multi_json (~> 1.0)
117
120
  rack (~> 1.0)
118
121
  tilt (~> 1.1, != 1.3.0)
119
- sprockets-rails (2.0.0)
122
+ sprockets-rails (2.0.1)
120
123
  actionpack (>= 3.0)
121
124
  activesupport (>= 3.0)
122
125
  sprockets (~> 2.8)
@@ -130,11 +133,11 @@ GEM
130
133
  polyglot (>= 0.3.1)
131
134
  turbolinks (1.3.0)
132
135
  coffee-rails
133
- tzinfo (0.3.37)
134
- uglifier (2.2.1)
136
+ tzinfo (0.3.38)
137
+ uglifier (2.3.0)
135
138
  execjs (>= 0.3.0)
136
- multi_json (~> 1.0, >= 1.0.2)
137
- webmock (1.13.0)
139
+ json (>= 1.8.0)
140
+ webmock (1.15.2)
138
141
  addressable (>= 2.2.7)
139
142
  crack (>= 0.3.2)
140
143
 
@@ -146,7 +149,7 @@ DEPENDENCIES
146
149
  jbuilder (~> 1.2)
147
150
  jquery-rails
148
151
  qa!
149
- rails (= 4.0.0)
152
+ rails (= 4.0.1)
150
153
  rspec-rails
151
154
  sass-rails (~> 4.0.0)
152
155
  sdoc