zipme-thinking-sphinx 1.3.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. data/LICENCE +20 -0
  2. data/README.textile +168 -0
  3. data/VERSION +1 -0
  4. data/features/abstract_inheritance.feature +10 -0
  5. data/features/alternate_primary_key.feature +27 -0
  6. data/features/attribute_transformation.feature +22 -0
  7. data/features/attribute_updates.feature +51 -0
  8. data/features/deleting_instances.feature +67 -0
  9. data/features/direct_attributes.feature +11 -0
  10. data/features/excerpts.feature +13 -0
  11. data/features/extensible_delta_indexing.feature +9 -0
  12. data/features/facets.feature +82 -0
  13. data/features/facets_across_model.feature +29 -0
  14. data/features/handling_edits.feature +92 -0
  15. data/features/retry_stale_indexes.feature +24 -0
  16. data/features/searching_across_models.feature +20 -0
  17. data/features/searching_by_index.feature +40 -0
  18. data/features/searching_by_model.feature +175 -0
  19. data/features/searching_with_find_arguments.feature +56 -0
  20. data/features/sphinx_detection.feature +25 -0
  21. data/features/sphinx_scopes.feature +42 -0
  22. data/features/step_definitions/alpha_steps.rb +16 -0
  23. data/features/step_definitions/beta_steps.rb +7 -0
  24. data/features/step_definitions/common_steps.rb +188 -0
  25. data/features/step_definitions/extensible_delta_indexing_steps.rb +7 -0
  26. data/features/step_definitions/facet_steps.rb +96 -0
  27. data/features/step_definitions/find_arguments_steps.rb +36 -0
  28. data/features/step_definitions/gamma_steps.rb +15 -0
  29. data/features/step_definitions/scope_steps.rb +15 -0
  30. data/features/step_definitions/search_steps.rb +89 -0
  31. data/features/step_definitions/sphinx_steps.rb +35 -0
  32. data/features/sti_searching.feature +19 -0
  33. data/features/support/database.example.yml +3 -0
  34. data/features/support/db/fixtures/alphas.rb +10 -0
  35. data/features/support/db/fixtures/authors.rb +1 -0
  36. data/features/support/db/fixtures/betas.rb +10 -0
  37. data/features/support/db/fixtures/boxes.rb +9 -0
  38. data/features/support/db/fixtures/categories.rb +1 -0
  39. data/features/support/db/fixtures/cats.rb +3 -0
  40. data/features/support/db/fixtures/comments.rb +24 -0
  41. data/features/support/db/fixtures/developers.rb +29 -0
  42. data/features/support/db/fixtures/dogs.rb +3 -0
  43. data/features/support/db/fixtures/extensible_betas.rb +10 -0
  44. data/features/support/db/fixtures/foxes.rb +3 -0
  45. data/features/support/db/fixtures/gammas.rb +10 -0
  46. data/features/support/db/fixtures/music.rb +4 -0
  47. data/features/support/db/fixtures/people.rb +1001 -0
  48. data/features/support/db/fixtures/posts.rb +6 -0
  49. data/features/support/db/fixtures/robots.rb +14 -0
  50. data/features/support/db/fixtures/tags.rb +27 -0
  51. data/features/support/db/migrations/create_alphas.rb +8 -0
  52. data/features/support/db/migrations/create_animals.rb +5 -0
  53. data/features/support/db/migrations/create_authors.rb +3 -0
  54. data/features/support/db/migrations/create_authors_posts.rb +6 -0
  55. data/features/support/db/migrations/create_betas.rb +5 -0
  56. data/features/support/db/migrations/create_boxes.rb +5 -0
  57. data/features/support/db/migrations/create_categories.rb +3 -0
  58. data/features/support/db/migrations/create_comments.rb +10 -0
  59. data/features/support/db/migrations/create_developers.rb +9 -0
  60. data/features/support/db/migrations/create_extensible_betas.rb +5 -0
  61. data/features/support/db/migrations/create_gammas.rb +3 -0
  62. data/features/support/db/migrations/create_genres.rb +3 -0
  63. data/features/support/db/migrations/create_music.rb +6 -0
  64. data/features/support/db/migrations/create_people.rb +13 -0
  65. data/features/support/db/migrations/create_posts.rb +5 -0
  66. data/features/support/db/migrations/create_robots.rb +4 -0
  67. data/features/support/db/migrations/create_taggings.rb +5 -0
  68. data/features/support/db/migrations/create_tags.rb +4 -0
  69. data/features/support/env.rb +21 -0
  70. data/features/support/lib/generic_delta_handler.rb +8 -0
  71. data/features/support/models/alpha.rb +22 -0
  72. data/features/support/models/animal.rb +5 -0
  73. data/features/support/models/author.rb +3 -0
  74. data/features/support/models/beta.rb +8 -0
  75. data/features/support/models/box.rb +8 -0
  76. data/features/support/models/cat.rb +3 -0
  77. data/features/support/models/category.rb +4 -0
  78. data/features/support/models/comment.rb +10 -0
  79. data/features/support/models/developer.rb +16 -0
  80. data/features/support/models/dog.rb +3 -0
  81. data/features/support/models/extensible_beta.rb +9 -0
  82. data/features/support/models/fox.rb +5 -0
  83. data/features/support/models/gamma.rb +5 -0
  84. data/features/support/models/genre.rb +3 -0
  85. data/features/support/models/medium.rb +5 -0
  86. data/features/support/models/music.rb +8 -0
  87. data/features/support/models/person.rb +23 -0
  88. data/features/support/models/post.rb +21 -0
  89. data/features/support/models/robot.rb +12 -0
  90. data/features/support/models/tag.rb +3 -0
  91. data/features/support/models/tagging.rb +4 -0
  92. data/lib/cucumber/thinking_sphinx/external_world.rb +8 -0
  93. data/lib/cucumber/thinking_sphinx/internal_world.rb +126 -0
  94. data/lib/cucumber/thinking_sphinx/sql_logger.rb +20 -0
  95. data/lib/thinking_sphinx.rb +231 -0
  96. data/lib/thinking_sphinx/active_record.rb +373 -0
  97. data/lib/thinking_sphinx/active_record/attribute_updates.rb +46 -0
  98. data/lib/thinking_sphinx/active_record/delta.rb +61 -0
  99. data/lib/thinking_sphinx/active_record/has_many_association.rb +29 -0
  100. data/lib/thinking_sphinx/active_record/scopes.rb +75 -0
  101. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +42 -0
  102. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +54 -0
  103. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +143 -0
  104. data/lib/thinking_sphinx/association.rb +164 -0
  105. data/lib/thinking_sphinx/attribute.rb +362 -0
  106. data/lib/thinking_sphinx/auto_version.rb +22 -0
  107. data/lib/thinking_sphinx/class_facet.rb +15 -0
  108. data/lib/thinking_sphinx/configuration.rb +283 -0
  109. data/lib/thinking_sphinx/context.rb +68 -0
  110. data/lib/thinking_sphinx/core/array.rb +7 -0
  111. data/lib/thinking_sphinx/core/string.rb +15 -0
  112. data/lib/thinking_sphinx/deltas.rb +28 -0
  113. data/lib/thinking_sphinx/deltas/default_delta.rb +62 -0
  114. data/lib/thinking_sphinx/deploy/capistrano.rb +100 -0
  115. data/lib/thinking_sphinx/excerpter.rb +22 -0
  116. data/lib/thinking_sphinx/facet.rb +125 -0
  117. data/lib/thinking_sphinx/facet_search.rb +136 -0
  118. data/lib/thinking_sphinx/field.rb +82 -0
  119. data/lib/thinking_sphinx/index.rb +157 -0
  120. data/lib/thinking_sphinx/index/builder.rb +296 -0
  121. data/lib/thinking_sphinx/index/faux_column.rb +110 -0
  122. data/lib/thinking_sphinx/property.rb +162 -0
  123. data/lib/thinking_sphinx/rails_additions.rb +150 -0
  124. data/lib/thinking_sphinx/search.rb +775 -0
  125. data/lib/thinking_sphinx/search_methods.rb +439 -0
  126. data/lib/thinking_sphinx/source.rb +153 -0
  127. data/lib/thinking_sphinx/source/internal_properties.rb +46 -0
  128. data/lib/thinking_sphinx/source/sql.rb +130 -0
  129. data/lib/thinking_sphinx/tasks.rb +121 -0
  130. data/lib/thinking_sphinx/test.rb +52 -0
  131. data/rails/init.rb +16 -0
  132. data/spec/thinking_sphinx/active_record/delta_spec.rb +128 -0
  133. data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +55 -0
  134. data/spec/thinking_sphinx/active_record/scopes_spec.rb +177 -0
  135. data/spec/thinking_sphinx/active_record_spec.rb +622 -0
  136. data/spec/thinking_sphinx/association_spec.rb +239 -0
  137. data/spec/thinking_sphinx/attribute_spec.rb +570 -0
  138. data/spec/thinking_sphinx/auto_version_spec.rb +39 -0
  139. data/spec/thinking_sphinx/configuration_spec.rb +234 -0
  140. data/spec/thinking_sphinx/context_spec.rb +119 -0
  141. data/spec/thinking_sphinx/core/array_spec.rb +9 -0
  142. data/spec/thinking_sphinx/core/string_spec.rb +9 -0
  143. data/spec/thinking_sphinx/excerpter_spec.rb +57 -0
  144. data/spec/thinking_sphinx/facet_search_spec.rb +176 -0
  145. data/spec/thinking_sphinx/facet_spec.rb +333 -0
  146. data/spec/thinking_sphinx/field_spec.rb +154 -0
  147. data/spec/thinking_sphinx/index/builder_spec.rb +479 -0
  148. data/spec/thinking_sphinx/index/faux_column_spec.rb +30 -0
  149. data/spec/thinking_sphinx/index_spec.rb +183 -0
  150. data/spec/thinking_sphinx/rails_additions_spec.rb +203 -0
  151. data/spec/thinking_sphinx/search_methods_spec.rb +152 -0
  152. data/spec/thinking_sphinx/search_spec.rb +1181 -0
  153. data/spec/thinking_sphinx/source_spec.rb +235 -0
  154. data/spec/thinking_sphinx_spec.rb +204 -0
  155. data/tasks/distribution.rb +39 -0
  156. data/tasks/rails.rake +1 -0
  157. data/tasks/testing.rb +72 -0
  158. metadata +242 -0
data/tasks/rails.rake ADDED
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), '/../lib/thinking_sphinx/tasks')
data/tasks/testing.rb ADDED
@@ -0,0 +1,72 @@
1
+ require 'rubygems'
2
+ require 'spec/rake/spectask'
3
+ require 'cucumber/rake/task'
4
+
5
+ desc "Run the specs under spec"
6
+ Spec::Rake::SpecTask.new do |t|
7
+ t.spec_files = FileList['spec/**/*_spec.rb']
8
+ t.spec_opts << "-c"
9
+ end
10
+
11
+ desc "Run all feature-set configurations"
12
+ task :features do |t|
13
+ databases = ENV['DATABASES'] || 'mysql,postgresql'
14
+ databases.split(',').each do |database|
15
+ puts "rake features:#{database}"
16
+ system "rake features:#{database}"
17
+ end
18
+ end
19
+
20
+ namespace :features do
21
+ def add_task(name, description)
22
+ Cucumber::Rake::Task.new(name, description) do |t|
23
+ t.cucumber_opts = "--format pretty features/*.feature DATABASE=#{name}"
24
+ end
25
+ end
26
+
27
+ add_task :mysql, "Run feature-set against MySQL"
28
+ add_task :postgresql, "Run feature-set against PostgreSQL"
29
+ end
30
+
31
+ desc "Generate RCov reports"
32
+ Spec::Rake::SpecTask.new(:rcov) do |t|
33
+ t.libs << 'lib'
34
+ t.spec_files = FileList['spec/**/*_spec.rb']
35
+ t.rcov = true
36
+ t.rcov_opts = [
37
+ '--exclude', 'spec',
38
+ '--exclude', 'gems',
39
+ '--exclude', 'riddle',
40
+ '--exclude', 'ruby'
41
+ ]
42
+ end
43
+
44
+ namespace :rcov do
45
+ def add_task(name, description)
46
+ Cucumber::Rake::Task.new(name, description) do |t|
47
+ t.cucumber_opts = "--format pretty"
48
+ t.profile = name
49
+ t.rcov = true
50
+ t.rcov_opts = [
51
+ '--exclude', 'spec',
52
+ '--exclude', 'gems',
53
+ '--exclude', 'riddle',
54
+ '--exclude', 'features'
55
+ ]
56
+ end
57
+ end
58
+
59
+ add_task :mysql, "Run feature-set against MySQL with rcov"
60
+ add_task :postgresql, "Run feature-set against PostgreSQL with rcov"
61
+ end
62
+
63
+ desc "Build cucumber.yml file"
64
+ task :cucumber_defaults do
65
+ steps = FileList["features/step_definitions/**.rb"].collect { |path|
66
+ "--require #{path}"
67
+ }.join(" ")
68
+
69
+ File.open('cucumber.yml', 'w') { |f|
70
+ f.write "default: \"--require features/support/env.rb #{steps}\"\n"
71
+ }
72
+ end
metadata ADDED
@@ -0,0 +1,242 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zipme-thinking-sphinx
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.3.14
5
+ platform: ruby
6
+ authors:
7
+ - Pat Allan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-22 00:00:00 +08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activerecord
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.15.6
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: riddle
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.8
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: after_commit
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.0.5
44
+ version:
45
+ description: A concise and easy-to-use Ruby library that connects ActiveRecord to the Sphinx search daemon, managing configuration, indexing and searching.
46
+ email: pat@freelancing-gods.com
47
+ executables: []
48
+
49
+ extensions: []
50
+
51
+ extra_rdoc_files:
52
+ - README.textile
53
+ files:
54
+ - LICENCE
55
+ - README.textile
56
+ - VERSION
57
+ - lib/cucumber/thinking_sphinx/external_world.rb
58
+ - lib/cucumber/thinking_sphinx/internal_world.rb
59
+ - lib/cucumber/thinking_sphinx/sql_logger.rb
60
+ - lib/thinking_sphinx.rb
61
+ - lib/thinking_sphinx/active_record.rb
62
+ - lib/thinking_sphinx/active_record/attribute_updates.rb
63
+ - lib/thinking_sphinx/active_record/delta.rb
64
+ - lib/thinking_sphinx/active_record/has_many_association.rb
65
+ - lib/thinking_sphinx/active_record/scopes.rb
66
+ - lib/thinking_sphinx/adapters/abstract_adapter.rb
67
+ - lib/thinking_sphinx/adapters/mysql_adapter.rb
68
+ - lib/thinking_sphinx/adapters/postgresql_adapter.rb
69
+ - lib/thinking_sphinx/association.rb
70
+ - lib/thinking_sphinx/attribute.rb
71
+ - lib/thinking_sphinx/auto_version.rb
72
+ - lib/thinking_sphinx/class_facet.rb
73
+ - lib/thinking_sphinx/configuration.rb
74
+ - lib/thinking_sphinx/context.rb
75
+ - lib/thinking_sphinx/core/array.rb
76
+ - lib/thinking_sphinx/core/string.rb
77
+ - lib/thinking_sphinx/deltas.rb
78
+ - lib/thinking_sphinx/deltas/default_delta.rb
79
+ - lib/thinking_sphinx/deploy/capistrano.rb
80
+ - lib/thinking_sphinx/excerpter.rb
81
+ - lib/thinking_sphinx/facet.rb
82
+ - lib/thinking_sphinx/facet_search.rb
83
+ - lib/thinking_sphinx/field.rb
84
+ - lib/thinking_sphinx/index.rb
85
+ - lib/thinking_sphinx/index/builder.rb
86
+ - lib/thinking_sphinx/index/faux_column.rb
87
+ - lib/thinking_sphinx/property.rb
88
+ - lib/thinking_sphinx/rails_additions.rb
89
+ - lib/thinking_sphinx/search.rb
90
+ - lib/thinking_sphinx/search_methods.rb
91
+ - lib/thinking_sphinx/source.rb
92
+ - lib/thinking_sphinx/source/internal_properties.rb
93
+ - lib/thinking_sphinx/source/sql.rb
94
+ - lib/thinking_sphinx/tasks.rb
95
+ - lib/thinking_sphinx/test.rb
96
+ - rails/init.rb
97
+ - tasks/distribution.rb
98
+ - tasks/rails.rake
99
+ - tasks/testing.rb
100
+ has_rdoc: true
101
+ homepage: http://ts.freelancing-gods.com
102
+ licenses: []
103
+
104
+ post_install_message: |+
105
+ If you're upgrading, you should read this:
106
+ http://freelancing-god.github.com/ts/en/upgrading.html
107
+
108
+ rdoc_options:
109
+ - --charset=UTF-8
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: "0"
117
+ version:
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: "0"
123
+ version:
124
+ requirements: []
125
+
126
+ rubyforge_project:
127
+ rubygems_version: 1.3.5
128
+ signing_key:
129
+ specification_version: 3
130
+ summary: ActiveRecord/Rails Sphinx library
131
+ test_files:
132
+ - features/abstract_inheritance.feature
133
+ - features/alternate_primary_key.feature
134
+ - features/attribute_transformation.feature
135
+ - features/attribute_updates.feature
136
+ - features/deleting_instances.feature
137
+ - features/direct_attributes.feature
138
+ - features/excerpts.feature
139
+ - features/extensible_delta_indexing.feature
140
+ - features/facets.feature
141
+ - features/facets_across_model.feature
142
+ - features/handling_edits.feature
143
+ - features/retry_stale_indexes.feature
144
+ - features/searching_across_models.feature
145
+ - features/searching_by_index.feature
146
+ - features/searching_by_model.feature
147
+ - features/searching_with_find_arguments.feature
148
+ - features/sphinx_detection.feature
149
+ - features/sphinx_scopes.feature
150
+ - features/step_definitions/alpha_steps.rb
151
+ - features/step_definitions/beta_steps.rb
152
+ - features/step_definitions/common_steps.rb
153
+ - features/step_definitions/extensible_delta_indexing_steps.rb
154
+ - features/step_definitions/facet_steps.rb
155
+ - features/step_definitions/find_arguments_steps.rb
156
+ - features/step_definitions/gamma_steps.rb
157
+ - features/step_definitions/scope_steps.rb
158
+ - features/step_definitions/search_steps.rb
159
+ - features/step_definitions/sphinx_steps.rb
160
+ - features/sti_searching.feature
161
+ - features/support/database.example.yml
162
+ - features/support/db/fixtures/alphas.rb
163
+ - features/support/db/fixtures/authors.rb
164
+ - features/support/db/fixtures/betas.rb
165
+ - features/support/db/fixtures/boxes.rb
166
+ - features/support/db/fixtures/categories.rb
167
+ - features/support/db/fixtures/cats.rb
168
+ - features/support/db/fixtures/comments.rb
169
+ - features/support/db/fixtures/developers.rb
170
+ - features/support/db/fixtures/dogs.rb
171
+ - features/support/db/fixtures/extensible_betas.rb
172
+ - features/support/db/fixtures/foxes.rb
173
+ - features/support/db/fixtures/gammas.rb
174
+ - features/support/db/fixtures/music.rb
175
+ - features/support/db/fixtures/people.rb
176
+ - features/support/db/fixtures/posts.rb
177
+ - features/support/db/fixtures/robots.rb
178
+ - features/support/db/fixtures/tags.rb
179
+ - features/support/db/migrations/create_alphas.rb
180
+ - features/support/db/migrations/create_animals.rb
181
+ - features/support/db/migrations/create_authors.rb
182
+ - features/support/db/migrations/create_authors_posts.rb
183
+ - features/support/db/migrations/create_betas.rb
184
+ - features/support/db/migrations/create_boxes.rb
185
+ - features/support/db/migrations/create_categories.rb
186
+ - features/support/db/migrations/create_comments.rb
187
+ - features/support/db/migrations/create_developers.rb
188
+ - features/support/db/migrations/create_extensible_betas.rb
189
+ - features/support/db/migrations/create_gammas.rb
190
+ - features/support/db/migrations/create_genres.rb
191
+ - features/support/db/migrations/create_music.rb
192
+ - features/support/db/migrations/create_people.rb
193
+ - features/support/db/migrations/create_posts.rb
194
+ - features/support/db/migrations/create_robots.rb
195
+ - features/support/db/migrations/create_taggings.rb
196
+ - features/support/db/migrations/create_tags.rb
197
+ - features/support/env.rb
198
+ - features/support/lib/generic_delta_handler.rb
199
+ - features/support/models/alpha.rb
200
+ - features/support/models/animal.rb
201
+ - features/support/models/author.rb
202
+ - features/support/models/beta.rb
203
+ - features/support/models/box.rb
204
+ - features/support/models/cat.rb
205
+ - features/support/models/category.rb
206
+ - features/support/models/comment.rb
207
+ - features/support/models/developer.rb
208
+ - features/support/models/dog.rb
209
+ - features/support/models/extensible_beta.rb
210
+ - features/support/models/fox.rb
211
+ - features/support/models/gamma.rb
212
+ - features/support/models/genre.rb
213
+ - features/support/models/medium.rb
214
+ - features/support/models/music.rb
215
+ - features/support/models/person.rb
216
+ - features/support/models/post.rb
217
+ - features/support/models/robot.rb
218
+ - features/support/models/tag.rb
219
+ - features/support/models/tagging.rb
220
+ - spec/thinking_sphinx/active_record/delta_spec.rb
221
+ - spec/thinking_sphinx/active_record/has_many_association_spec.rb
222
+ - spec/thinking_sphinx/active_record/scopes_spec.rb
223
+ - spec/thinking_sphinx/active_record_spec.rb
224
+ - spec/thinking_sphinx/association_spec.rb
225
+ - spec/thinking_sphinx/attribute_spec.rb
226
+ - spec/thinking_sphinx/auto_version_spec.rb
227
+ - spec/thinking_sphinx/configuration_spec.rb
228
+ - spec/thinking_sphinx/context_spec.rb
229
+ - spec/thinking_sphinx/core/array_spec.rb
230
+ - spec/thinking_sphinx/core/string_spec.rb
231
+ - spec/thinking_sphinx/excerpter_spec.rb
232
+ - spec/thinking_sphinx/facet_search_spec.rb
233
+ - spec/thinking_sphinx/facet_spec.rb
234
+ - spec/thinking_sphinx/field_spec.rb
235
+ - spec/thinking_sphinx/index/builder_spec.rb
236
+ - spec/thinking_sphinx/index/faux_column_spec.rb
237
+ - spec/thinking_sphinx/index_spec.rb
238
+ - spec/thinking_sphinx/rails_additions_spec.rb
239
+ - spec/thinking_sphinx/search_methods_spec.rb
240
+ - spec/thinking_sphinx/search_spec.rb
241
+ - spec/thinking_sphinx/source_spec.rb
242
+ - spec/thinking_sphinx_spec.rb