PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/spec/rails_admin/adapters/active_record_spec.rb

https://github.com/mnashimoto/rails_admin
Ruby | 320 lines | 273 code | 47 blank | 0 comment | 3 complexity | fd74692ad476dd60809c1b48a517f50a MD5 | raw file
  1. require 'spec_helper'
  2. require 'timecop'
  3. describe 'RailsAdmin::Adapters::ActiveRecord', active_record: true do
  4. before do
  5. @like = ::ActiveRecord::Base.configurations[Rails.env]['adapter'] == 'postgresql' ? 'ILIKE' : 'LIKE'
  6. end
  7. describe '#associations' do
  8. it 'returns Association class' do
  9. expect(RailsAdmin::AbstractModel.new(Player).associations.first).
  10. to be_a_kind_of RailsAdmin::Adapters::ActiveRecord::Association
  11. end
  12. end
  13. describe '#properties' do
  14. it 'returns Property class' do
  15. expect(RailsAdmin::AbstractModel.new(Player).properties.first).
  16. to be_a_kind_of RailsAdmin::Adapters::ActiveRecord::Property
  17. end
  18. end
  19. describe 'data access methods' do
  20. before do
  21. @players = FactoryGirl.create_list(:player, 3)
  22. @abstract_model = RailsAdmin::AbstractModel.new('Player')
  23. end
  24. it '#new returns instance of AbstractObject' do
  25. expect(@abstract_model.new.object).to be_instance_of(Player)
  26. end
  27. it '#get returns instance of AbstractObject' do
  28. expect(@abstract_model.get(@players.first.id).object).to eq(@players.first)
  29. end
  30. it '#get returns nil when id does not exist' do
  31. expect(@abstract_model.get('abc')).to be_nil
  32. end
  33. it '#first returns a player' do
  34. expect(@players).to include @abstract_model.first
  35. end
  36. it '#count returns count of items' do
  37. expect(@abstract_model.count).to eq(@players.count)
  38. end
  39. it '#destroy destroys multiple items' do
  40. @abstract_model.destroy(@players[0..1])
  41. expect(Player.all).to eq(@players[2..2])
  42. end
  43. it '#where returns filtered results' do
  44. expect(@abstract_model.where(name: @players.first.name)).to eq([@players.first])
  45. end
  46. describe '#all' do
  47. it 'works without options' do
  48. expect(@abstract_model.all).to match_array @players
  49. end
  50. it 'supports eager loading' do
  51. expect(@abstract_model.all(include: :team).includes_values).to eq([:team])
  52. end
  53. it 'supports limiting' do
  54. expect(@abstract_model.all(limit: 2)).to have(2).items
  55. end
  56. it 'supports retrieval by bulk_ids' do
  57. expect(@abstract_model.all(bulk_ids: @players[0..1].collect(&:id))).to match_array @players[0..1]
  58. end
  59. it 'supports pagination' do
  60. expect(@abstract_model.all(sort: 'id', page: 2, per: 1)).to eq(@players[1..1])
  61. expect(@abstract_model.all(sort: 'id', page: 1, per: 2)).to eq(@players[1..2].reverse)
  62. end
  63. it 'supports ordering' do
  64. expect(@abstract_model.all(sort: 'id', sort_reverse: true)).to eq(@players.sort)
  65. end
  66. it 'supports querying' do
  67. expect(@abstract_model.all(query: @players[1].name)).to eq(@players[1..1])
  68. end
  69. it 'supports filtering' do
  70. expect(@abstract_model.all(filters: {'name' => {'0000' => {o: 'is', v: @players[1].name}}})).to eq(@players[1..1])
  71. end
  72. end
  73. end
  74. describe '#query_conditions' do
  75. before do
  76. @abstract_model = RailsAdmin::AbstractModel.new('Team')
  77. @teams = [{}, {name: 'somewhere foos'}, {manager: 'foo junior'}].
  78. collect { |h| FactoryGirl.create :team, h }
  79. end
  80. it 'makes correct query' do
  81. expect(@abstract_model.all(query: 'foo')).to match_array @teams[1..2]
  82. end
  83. context "when field's searchable_columns is empty" do
  84. before do
  85. RailsAdmin.config do |c|
  86. c.model Team do
  87. field :players
  88. end
  89. end
  90. end
  91. it 'does not break' do
  92. expect { @abstract_model.all(query: 'foo') }.not_to raise_error
  93. end
  94. end
  95. end
  96. describe '#filter_conditions' do
  97. before do
  98. @abstract_model = RailsAdmin::AbstractModel.new('Team')
  99. @division = FactoryGirl.create :division, name: 'bar division'
  100. @teams = [{}, {division: @division}, {name: 'somewhere foos', division: @division}, {name: 'nowhere foos'}].
  101. collect { |h| FactoryGirl.create :team, h }
  102. end
  103. context 'without configuration' do
  104. before do
  105. Rails.configuration.stub(:database_configuration) { nil }
  106. end
  107. after do
  108. Rails.configuration.unstub(:database_configuration)
  109. end
  110. it 'does not raise error' do
  111. expect { @abstract_model.all(filters: {'name' => {'0000' => {o: 'like', v: 'foo'}}}) }.to_not raise_error
  112. end
  113. end
  114. it 'makes correct query' do
  115. expect(@abstract_model.all(filters: {'name' => {'0000' => {o: 'like', v: 'foo'}}, 'division' => {'0001' => {o: 'like', v: 'bar'}}}, include: :division)).to eq([@teams[2]])
  116. end
  117. end
  118. describe '#build_statement' do
  119. before do
  120. @abstract_model = RailsAdmin::AbstractModel.new('FieldTest')
  121. end
  122. it "ignores '_discard' operator or value" do
  123. [['_discard', ''], ['', '_discard']].each do |value, operator|
  124. expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to be_nil
  125. end
  126. end
  127. it "supports '_blank' operator" do
  128. [['_blank', ''], ['', '_blank']].each do |value, operator|
  129. expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq(["(name IS NULL OR name = '')"])
  130. end
  131. end
  132. it "supports '_present' operator" do
  133. [['_present', ''], ['', '_present']].each do |value, operator|
  134. expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq(["(name IS NOT NULL AND name != '')"])
  135. end
  136. end
  137. it "supports '_null' operator" do
  138. [['_null', ''], ['', '_null']].each do |value, operator|
  139. expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq(['(name IS NULL)'])
  140. end
  141. end
  142. it "supports '_not_null' operator" do
  143. [['_not_null', ''], ['', '_not_null']].each do |value, operator|
  144. expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq(['(name IS NOT NULL)'])
  145. end
  146. end
  147. it "supports '_empty' operator" do
  148. [['_empty', ''], ['', '_empty']].each do |value, operator|
  149. expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq(["(name = '')"])
  150. end
  151. end
  152. it "supports '_not_empty' operator" do
  153. [['_not_empty', ''], ['', '_not_empty']].each do |value, operator|
  154. expect(@abstract_model.send(:build_statement, :name, :string, value, operator)).to eq(["(name != '')"])
  155. end
  156. end
  157. it 'supports boolean type query' do
  158. %w[false f 0].each do |value|
  159. expect(@abstract_model.send(:build_statement, :field, :boolean, value, nil)).to eq(['(field IS NULL OR field = ?)', false])
  160. end
  161. %w[true t 1].each do |value|
  162. expect(@abstract_model.send(:build_statement, :field, :boolean, value, nil)).to eq(['(field = ?)', true])
  163. end
  164. expect(@abstract_model.send(:build_statement, :field, :boolean, 'word', nil)).to be_nil
  165. end
  166. it 'supports integer type query' do
  167. expect(@abstract_model.send(:build_statement, :field, :integer, '1' , nil)).to eq(['(field = ?)', 1])
  168. expect(@abstract_model.send(:build_statement, :field, :integer, 'word', nil)).to be_nil
  169. expect(@abstract_model.send(:build_statement, :field, :integer, '1' , 'default')).to eq(['(field = ?)', 1])
  170. expect(@abstract_model.send(:build_statement, :field, :integer, 'word', 'default')).to be_nil
  171. expect(@abstract_model.send(:build_statement, :field, :integer, '1' , 'between')).to eq(['(field = ?)', 1])
  172. expect(@abstract_model.send(:build_statement, :field, :integer, 'word', 'between')).to be_nil
  173. expect(@abstract_model.send(:build_statement, :field, :integer, ['6', '' , ''], 'default')).to eq(['(field = ?)', 6])
  174. expect(@abstract_model.send(:build_statement, :field, :integer, ['7', '10', ''], 'default')).to eq(['(field = ?)', 7])
  175. expect(@abstract_model.send(:build_statement, :field, :integer, ['8', '' , '20'], 'default')).to eq(['(field = ?)', 8])
  176. expect(@abstract_model.send(:build_statement, :field, :integer, %w[9 10 20], 'default')).to eq(['(field = ?)', 9])
  177. end
  178. it 'supports integer type range query' do
  179. expect(@abstract_model.send(:build_statement, :field, :integer, ['', '', ''], 'between')).to be_nil
  180. expect(@abstract_model.send(:build_statement, :field, :integer, ['2', '', ''], 'between')).to be_nil
  181. expect(@abstract_model.send(:build_statement, :field, :integer, ['', '3', ''], 'between')).to eq(['(field >= ?)', 3])
  182. expect(@abstract_model.send(:build_statement, :field, :integer, ['', '', '5'], 'between')).to eq(['(field <= ?)', 5])
  183. expect(@abstract_model.send(:build_statement, :field, :integer, ['' , '10', '20'], 'between')).to eq(['(field BETWEEN ? AND ?)', 10, 20])
  184. expect(@abstract_model.send(:build_statement, :field, :integer, %w[15 10 20], 'between')).to eq(['(field BETWEEN ? AND ?)', 10, 20])
  185. expect(@abstract_model.send(:build_statement, :field, :integer, ['', 'word1', ''], 'between')).to be_nil
  186. expect(@abstract_model.send(:build_statement, :field, :integer, ['', '' , 'word2'], 'between')).to be_nil
  187. expect(@abstract_model.send(:build_statement, :field, :integer, ['', 'word3', 'word4'], 'between')).to be_nil
  188. end
  189. it 'supports both decimal and float type queries' do
  190. expect(@abstract_model.send(:build_statement, :field, :decimal, '1.1', nil)).to eq(['(field = ?)', 1.1])
  191. expect(@abstract_model.send(:build_statement, :field, :decimal, 'word', nil)).to be_nil
  192. expect(@abstract_model.send(:build_statement, :field, :decimal, '1.1' , 'default')).to eq(['(field = ?)', 1.1])
  193. expect(@abstract_model.send(:build_statement, :field, :decimal, 'word', 'default')).to be_nil
  194. expect(@abstract_model.send(:build_statement, :field, :decimal, '1.1' , 'between')).to eq(['(field = ?)', 1.1])
  195. expect(@abstract_model.send(:build_statement, :field, :decimal, 'word', 'between')).to be_nil
  196. expect(@abstract_model.send(:build_statement, :field, :decimal, ['6.1', '' , ''], 'default')).to eq(['(field = ?)', 6.1])
  197. expect(@abstract_model.send(:build_statement, :field, :decimal, ['7.1', '10.1', ''], 'default')).to eq(['(field = ?)', 7.1])
  198. expect(@abstract_model.send(:build_statement, :field, :decimal, ['8.1', '' , '20.1'], 'default')).to eq(['(field = ?)', 8.1])
  199. expect(@abstract_model.send(:build_statement, :field, :decimal, ['9.1', '10.1', '20.1'], 'default')).to eq(['(field = ?)', 9.1])
  200. expect(@abstract_model.send(:build_statement, :field, :decimal, ['', '', ''], 'between')).to be_nil
  201. expect(@abstract_model.send(:build_statement, :field, :decimal, ['2.1', '', ''], 'between')).to be_nil
  202. expect(@abstract_model.send(:build_statement, :field, :decimal, ['', '3.1', ''], 'between')).to eq(['(field >= ?)', 3.1])
  203. expect(@abstract_model.send(:build_statement, :field, :decimal, ['', '', '5.1'], 'between')).to eq(['(field <= ?)', 5.1])
  204. expect(@abstract_model.send(:build_statement, :field, :decimal, ['' , '10.1', '20.1'], 'between')).to eq(['(field BETWEEN ? AND ?)', 10.1, 20.1])
  205. expect(@abstract_model.send(:build_statement, :field, :decimal, ['15.1', '10.1', '20.1'], 'between')).to eq(['(field BETWEEN ? AND ?)', 10.1, 20.1])
  206. expect(@abstract_model.send(:build_statement, :field, :decimal, ['', 'word1', ''], 'between')).to be_nil
  207. expect(@abstract_model.send(:build_statement, :field, :decimal, ['', '' , 'word2'], 'between')).to be_nil
  208. expect(@abstract_model.send(:build_statement, :field, :decimal, ['', 'word3', 'word4'], 'between')).to be_nil
  209. expect(@abstract_model.send(:build_statement, :field, :float, '1.1', nil)).to eq(['(field = ?)', 1.1])
  210. expect(@abstract_model.send(:build_statement, :field, :float, 'word', nil)).to be_nil
  211. expect(@abstract_model.send(:build_statement, :field, :float, '1.1' , 'default')).to eq(['(field = ?)', 1.1])
  212. expect(@abstract_model.send(:build_statement, :field, :float, 'word', 'default')).to be_nil
  213. expect(@abstract_model.send(:build_statement, :field, :float, '1.1' , 'between')).to eq(['(field = ?)', 1.1])
  214. expect(@abstract_model.send(:build_statement, :field, :float, 'word', 'between')).to be_nil
  215. expect(@abstract_model.send(:build_statement, :field, :float, ['6.1', '' , ''], 'default')).to eq(['(field = ?)', 6.1])
  216. expect(@abstract_model.send(:build_statement, :field, :float, ['7.1', '10.1', ''], 'default')).to eq(['(field = ?)', 7.1])
  217. expect(@abstract_model.send(:build_statement, :field, :float, ['8.1', '' , '20.1'], 'default')).to eq(['(field = ?)', 8.1])
  218. expect(@abstract_model.send(:build_statement, :field, :float, ['9.1', '10.1', '20.1'], 'default')).to eq(['(field = ?)', 9.1])
  219. expect(@abstract_model.send(:build_statement, :field, :float, ['', '', ''], 'between')).to be_nil
  220. expect(@abstract_model.send(:build_statement, :field, :float, ['2.1', '', ''], 'between')).to be_nil
  221. expect(@abstract_model.send(:build_statement, :field, :float, ['', '3.1', ''], 'between')).to eq(['(field >= ?)', 3.1])
  222. expect(@abstract_model.send(:build_statement, :field, :float, ['', '', '5.1'], 'between')).to eq(['(field <= ?)', 5.1])
  223. expect(@abstract_model.send(:build_statement, :field, :float, ['' , '10.1', '20.1'], 'between')).to eq(['(field BETWEEN ? AND ?)', 10.1, 20.1])
  224. expect(@abstract_model.send(:build_statement, :field, :float, ['15.1', '10.1', '20.1'], 'between')).to eq(['(field BETWEEN ? AND ?)', 10.1, 20.1])
  225. expect(@abstract_model.send(:build_statement, :field, :float, ['', 'word1', ''], 'between')).to be_nil
  226. expect(@abstract_model.send(:build_statement, :field, :float, ['', '' , 'word2'], 'between')).to be_nil
  227. expect(@abstract_model.send(:build_statement, :field, :float, ['', 'word3', 'word4'], 'between')).to be_nil
  228. end
  229. it 'supports string type query' do
  230. expect(@abstract_model.send(:build_statement, :field, :string, '', nil)).to be_nil
  231. expect(@abstract_model.send(:build_statement, :field, :string, 'foo', 'was')).to be_nil
  232. expect(@abstract_model.send(:build_statement, :field, :string, 'foo', 'default')).to eq(["(LOWER(field) #{@like} ?)", '%foo%'])
  233. expect(@abstract_model.send(:build_statement, :field, :string, 'foo', 'like')).to eq(["(LOWER(field) #{@like} ?)", '%foo%'])
  234. expect(@abstract_model.send(:build_statement, :field, :string, 'foo', 'starts_with')).to eq(["(LOWER(field) #{@like} ?)", 'foo%'])
  235. expect(@abstract_model.send(:build_statement, :field, :string, 'foo', 'ends_with')).to eq(["(LOWER(field) #{@like} ?)", '%foo'])
  236. expect(@abstract_model.send(:build_statement, :field, :string, 'foo', 'is')).to eq(["(LOWER(field) #{@like} ?)", 'foo'])
  237. end
  238. it 'performs case-insensitive searches' do
  239. expect(@abstract_model.send(:build_statement, :field, :string, 'foo', 'default')).to eq(["(LOWER(field) #{@like} ?)", '%foo%'])
  240. expect(@abstract_model.send(:build_statement, :field, :string, 'FOO', 'default')).to eq(["(LOWER(field) #{@like} ?)", '%foo%'])
  241. end
  242. it 'supports date type query' do
  243. scope = FieldTest.all
  244. expect(@abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: ['', '01/02/2012', '01/03/2012'], o: 'between'}}).where_values).to eq(["(field_tests.date_field BETWEEN '2012-01-02' AND '2012-01-03')"])
  245. expect(@abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: ['', '01/03/2012', ''], o: 'between'}}).where_values).to eq(["(field_tests.date_field >= '2012-01-03')"])
  246. expect(@abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: ['', '', '01/02/2012'], o: 'between'}}).where_values).to eq(["(field_tests.date_field <= '2012-01-02')"])
  247. expect(@abstract_model.send(:filter_scope, scope, 'date_field' => {'1' => {v: ['01/02/2012'], o: 'default'}}).where_values).to eq(["(field_tests.date_field BETWEEN '2012-01-02' AND '2012-01-02')"])
  248. end
  249. it 'supports datetime type query' do
  250. scope = FieldTest.all
  251. expect(@abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: ['', '01/02/2012', '01/03/2012'], o: 'between'}}).where_values).to eq(scope.where(['(field_tests.datetime_field BETWEEN ? AND ?)', Time.local(2012, 1, 2), Time.local(2012, 1, 3).end_of_day]).where_values)
  252. expect(@abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: ['', '01/03/2012', ''], o: 'between'}}).where_values).to eq(scope.where(['(field_tests.datetime_field >= ?)', Time.local(2012, 1, 3)]).where_values)
  253. expect(@abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: ['', '', '01/02/2012'], o: 'between'}}).where_values).to eq(scope.where(['(field_tests.datetime_field <= ?)', Time.local(2012, 1, 2).end_of_day]).where_values)
  254. expect(@abstract_model.send(:filter_scope, scope, 'datetime_field' => {'1' => {v: ['01/02/2012'], o: 'default'}}).where_values).to eq(scope.where(['(field_tests.datetime_field BETWEEN ? AND ?)', Time.local(2012, 1, 2), Time.local(2012, 1, 2).end_of_day]).where_values)
  255. end
  256. it 'supports enum type query' do
  257. expect(@abstract_model.send(:build_statement, :field, :enum, '1', nil)).to eq(['(field IN (?))', ['1']])
  258. end
  259. end
  260. describe 'model attribute method' do
  261. before do
  262. @abstract_model = RailsAdmin::AbstractModel.new('Player')
  263. end
  264. it '#scoped returns relation object' do
  265. expect(@abstract_model.scoped).to be_a_kind_of(ActiveRecord::Relation)
  266. end
  267. it '#table_name works' do
  268. expect(@abstract_model.table_name).to eq('players')
  269. end
  270. end
  271. end