/spec/rails_best_practices/prepares/model_prepare_spec.rb

http://github.com/flyerhzm/rails_best_practices · Ruby · 433 lines · 403 code · 29 blank · 1 comment · 0 complexity · 89eb64de8bbf3cfd333965da86a1705c MD5 · raw file

  1. # frozen_string_literal: true
  2. require 'spec_helper'
  3. module RailsBestPractices
  4. module Prepares
  5. describe ModelPrepare do
  6. let(:runner) { Core::Runner.new(prepares: described_class.new) }
  7. context 'models' do
  8. it 'class_name with modules ::' do
  9. content = <<-EOF
  10. class Blog::Post < ActiveRecord::Base
  11. end
  12. EOF
  13. runner.prepare('app/models/admin/post.rb', content)
  14. models = Prepares.models
  15. expect(models.map(&:to_s)).to eq(['Blog::Post'])
  16. end
  17. it 'class_name with modules' do
  18. content = <<-EOF
  19. module Blog
  20. class Post < ActiveRecord::Base
  21. end
  22. end
  23. EOF
  24. runner.prepare('app/models/admin/post.rb', content)
  25. models = Prepares.models
  26. expect(models.map(&:to_s)).to eq(['Blog::Post'])
  27. end
  28. end
  29. context 'associations' do
  30. it 'parses model associations' do
  31. content = <<-EOF
  32. class Project < ActiveRecord::Base
  33. belongs_to :portfolio
  34. has_one :project_manager
  35. has_many :milestones
  36. has_and_belongs_to_many :categories
  37. end
  38. EOF
  39. runner.prepare('app/models/project.rb', content)
  40. model_associations = Prepares.model_associations
  41. expect(model_associations.get_association('Project', 'portfolio')).to eq(
  42. 'meta' => 'belongs_to', 'class_name' => 'Portfolio'
  43. )
  44. expect(model_associations.get_association('Project', 'project_manager')).to eq(
  45. 'meta' => 'has_one', 'class_name' => 'ProjectManager'
  46. )
  47. expect(model_associations.get_association('Project', 'milestones')).to eq(
  48. 'meta' => 'has_many', 'class_name' => 'Milestone'
  49. )
  50. expect(model_associations.get_association('Project', 'categories')).to eq(
  51. 'meta' => 'has_and_belongs_to_many', 'class_name' => 'Category'
  52. )
  53. end
  54. context 'with class_name option' do
  55. it 'parses belongs_to' do
  56. content = <<-EOF
  57. class Post < ActiveRecord::Base
  58. belongs_to :author, "class_name" => "Person"
  59. end
  60. EOF
  61. runner.prepare('app/models/post.rb', content)
  62. model_associations = Prepares.model_associations
  63. expect(model_associations.get_association('Post', 'author')).to eq(
  64. 'meta' => 'belongs_to', 'class_name' => 'Person'
  65. )
  66. end
  67. it 'parses has_one' do
  68. content = <<-EOF
  69. class Project < ActiveRecord::Base
  70. has_one :project_manager, "class_name" => "Person"
  71. end
  72. EOF
  73. runner.prepare('app/models/post.rb', content)
  74. model_associations = Prepares.model_associations
  75. expect(model_associations.get_association('Project', 'project_manager')).to eq(
  76. 'meta' => 'has_one', 'class_name' => 'Person'
  77. )
  78. end
  79. it 'parses has_many' do
  80. content = <<-EOF
  81. class Project < ActiveRecord::Base
  82. has_many :people, "class_name" => "Person"
  83. end
  84. EOF
  85. runner.prepare('app/models/project.rb', content)
  86. model_associations = Prepares.model_associations
  87. expect(model_associations.get_association('Project', 'people')).to eq(
  88. 'meta' => 'has_many', 'class_name' => 'Person'
  89. )
  90. end
  91. it 'parses has_and_belongs_to_many' do
  92. content = <<-EOF
  93. class Citizen < ActiveRecord::Base
  94. has_and_belongs_to_many :nations, "class_name" => "Country"
  95. end
  96. EOF
  97. runner.prepare('app/models/citizen.rb', content)
  98. model_associations = Prepares.model_associations
  99. expect(model_associations.get_association('Citizen', 'nations')).to eq(
  100. 'meta' => 'has_and_belongs_to_many', 'class_name' => 'Country'
  101. )
  102. end
  103. context 'namespace' do
  104. it 'parses with namespace' do
  105. content = <<-EOF
  106. class Community < ActiveRecord::Base
  107. has_many :members
  108. end
  109. EOF
  110. runner.prepare('app/models/community.rb', content)
  111. content = <<-EOF
  112. class Community::Member < ActiveRecord::Base
  113. belongs_to :community
  114. end
  115. EOF
  116. runner.prepare('app/models/community/member.rb', content)
  117. runner.after_prepare
  118. model_associations = Prepares.model_associations
  119. expect(model_associations.get_association('Community', 'members')).to eq(
  120. 'meta' => 'has_many', 'class_name' => 'Community::Member'
  121. )
  122. expect(model_associations.get_association('Community::Member', 'community')).to eq(
  123. 'meta' => 'belongs_to', 'class_name' => 'Community'
  124. )
  125. end
  126. it 'parses without namespace' do
  127. content = <<-EOF
  128. class Community::Member::Rating < ActiveRecord::Base
  129. belongs_to :member
  130. end
  131. EOF
  132. runner.prepare('app/models/community/member/rating.rb', content)
  133. content = <<-EOF
  134. class Community::Member < ActiveRecord::Base
  135. has_many :ratings
  136. end
  137. EOF
  138. runner.prepare('app/models/community/member.rb', content)
  139. runner.after_prepare
  140. model_associations = Prepares.model_associations
  141. expect(model_associations.get_association('Community::Member::Rating', 'member')).to eq(
  142. 'meta' => 'belongs_to', 'class_name' => 'Community::Member'
  143. )
  144. expect(model_associations.get_association('Community::Member', 'ratings')).to eq(
  145. 'meta' => 'has_many', 'class_name' => 'Community::Member::Rating'
  146. )
  147. end
  148. end
  149. end
  150. context 'mongoid embeds' do
  151. it 'parses embeds_many' do
  152. content = <<-EOF
  153. class Person
  154. include Mongoid::Document
  155. embeds_many :addresses
  156. end
  157. EOF
  158. runner.prepare('app/models/person.rb', content)
  159. model_associations = Prepares.model_associations
  160. expect(model_associations.get_association('Person', 'addresses')).to eq(
  161. 'meta' => 'embeds_many', 'class_name' => 'Address'
  162. )
  163. end
  164. it 'parses embeds_one' do
  165. content = <<-EOF
  166. class Lush
  167. include Mongoid::Document
  168. embeds_one :whiskey, class_name: "Drink", inverse_of: :alcoholic
  169. end
  170. EOF
  171. runner.prepare('app/models/lush.rb', content)
  172. model_associations = Prepares.model_associations
  173. expect(model_associations.get_association('Lush', 'whiskey')).to eq(
  174. 'meta' => 'embeds_one', 'class_name' => 'Drink'
  175. )
  176. end
  177. it 'parses embedded_in' do
  178. content = <<-EOF
  179. class Drink
  180. include Mongoid::Document
  181. embedded_in :alcoholic, class_name: "Lush", inverse_of: :whiskey
  182. end
  183. EOF
  184. runner.prepare('app/models/drink.rb', content)
  185. model_associations = Prepares.model_associations
  186. expect(model_associations.get_association('Drink', 'alcoholic')).to eq(
  187. 'meta' => 'embedded_in', 'class_name' => 'Lush'
  188. )
  189. end
  190. end
  191. context 'mongomapper many/one' do
  192. it 'parses one' do
  193. content = <<-EOF
  194. class Employee
  195. include MongoMapper::Document
  196. one :desk
  197. end
  198. EOF
  199. runner.prepare('app/models/employee.rb', content)
  200. model_associations = Prepares.model_associations
  201. expect(model_associations.get_association('Employee', 'desk')).to eq(
  202. 'meta' => 'one', 'class_name' => 'Desk'
  203. )
  204. end
  205. it 'parses many' do
  206. content = <<-EOF
  207. class Tree
  208. include MongoMapper::Document
  209. many :birds
  210. end
  211. EOF
  212. runner.prepare('app/models/tree.rb', content)
  213. model_associations = Prepares.model_associations
  214. expect(model_associations.get_association('Tree', 'birds')).to eq('meta' => 'many', 'class_name' => 'Bird')
  215. end
  216. end
  217. end
  218. context 'methods' do
  219. it 'parses model methods' do
  220. content = <<-EOF
  221. class Post < ActiveRecord::Base
  222. def save; end
  223. def find; end
  224. end
  225. EOF
  226. runner.prepare('app/models/post.rb', content)
  227. methods = Prepares.model_methods
  228. expect(methods.get_methods('Post').map(&:method_name)).to eq(%w[save find])
  229. end
  230. it 'parses model methods with access control' do
  231. content = <<-EOF
  232. class Post < ActiveRecord::Base
  233. def save; end
  234. def find; end
  235. protected
  236. def create_or_update; end
  237. private
  238. def find_by_sql; end
  239. end
  240. EOF
  241. runner.prepare('app/models/post.rb', content)
  242. methods = Prepares.model_methods
  243. expect(methods.get_methods('Post').map(&:method_name)).to eq(%w[save find create_or_update find_by_sql])
  244. expect(methods.get_methods('Post', 'public').map(&:method_name)).to eq(%w[save find])
  245. expect(methods.get_methods('Post', 'protected').map(&:method_name)).to eq(['create_or_update'])
  246. expect(methods.get_methods('Post', 'private').map(&:method_name)).to eq(['find_by_sql'])
  247. end
  248. it 'parses model methods with module ::' do
  249. content = <<-EOF
  250. class Admin::Blog::Post < ActiveRecord::Base
  251. def save; end
  252. def find; end
  253. end
  254. EOF
  255. runner.prepare('app/models/admin/blog/post.rb', content)
  256. methods = Prepares.model_methods
  257. expect(methods.get_methods('Admin::Blog::Post').map(&:method_name)).to eq(%w[save find])
  258. end
  259. it 'parses model methods with module' do
  260. content = <<-EOF
  261. module Admin
  262. module Blog
  263. class Post < ActiveRecord::Base
  264. def save; end
  265. def find; end
  266. end
  267. end
  268. end
  269. EOF
  270. runner.prepare('app/models/admin/blog/post.rb', content)
  271. methods = Prepares.model_methods
  272. expect(methods.get_methods('Admin::Blog::Post').map(&:method_name)).to eq(%w[save find])
  273. end
  274. it 'does not add methods from module' do
  275. content = <<-EOF
  276. class Model < ActiveRecord::Base
  277. end
  278. EOF
  279. runner.prepare('app/models/model.rb', content)
  280. content = <<-EOF
  281. module Mixin
  282. def mixed_method
  283. end
  284. end
  285. EOF
  286. runner.prepare('app/models/mixins/mixin.rb', content)
  287. methods = Prepares.model_methods
  288. expect(methods.get_methods('Model')).to be_empty
  289. end
  290. end
  291. context 'scope' do
  292. it 'treats named_scope as method' do
  293. content = <<-EOF
  294. class Post < ActiveRecord::Base
  295. named_scope :active, conditions: {active: true}
  296. end
  297. EOF
  298. runner.prepare('app/models/post.rb', content)
  299. methods = Prepares.model_methods
  300. expect(methods.get_methods('Post').map(&:method_name)).to eq(['active'])
  301. end
  302. it 'treats scope as method' do
  303. content = <<-EOF
  304. class Post < ActiveRecord::Base
  305. scope :active, where(active: true)
  306. end
  307. EOF
  308. runner.prepare('app/models/post.rb', content)
  309. methods = Prepares.model_methods
  310. expect(methods.get_methods('Post').map(&:method_name)).to eq(['active'])
  311. end
  312. end
  313. context 'alias' do
  314. it 'treats alias as method' do
  315. content = <<-EOF
  316. class Post < ActiveRecord::Base
  317. alias :new :old
  318. end
  319. EOF
  320. runner.prepare('app/models/post.rb', content)
  321. methods = Prepares.model_methods
  322. expect(methods.get_methods('Post').map(&:method_name)).to eq(['new'])
  323. end
  324. it 'treats alias_method as method' do
  325. content = <<-EOF
  326. class Post < ActiveRecord::Base
  327. alias_method :new, :old
  328. end
  329. EOF
  330. runner.prepare('app/models/post.rb', content)
  331. methods = Prepares.model_methods
  332. expect(methods.get_methods('Post').map(&:method_name)).to eq(['new'])
  333. end
  334. it 'treats alias_method_chain as method' do
  335. content = <<-EOF
  336. class Post < ActiveRecord::Base
  337. alias_method_chain :method, :feature
  338. end
  339. EOF
  340. runner.prepare('app/models/post.rb', content)
  341. methods = Prepares.model_methods
  342. expect(methods.get_methods('Post').map(&:method_name)).to eq(%w[method_with_feature method])
  343. end
  344. end
  345. context 'attributes' do
  346. it 'parses mongoid field' do
  347. content = <<-EOF
  348. class Post
  349. include Mongoid::Document
  350. field :title
  351. field :tags, type: Array
  352. field :comments_count, type: Integer
  353. field :deleted_at, type: DateTime
  354. field :active, type: Boolean
  355. end
  356. EOF
  357. runner.prepare('app/models/post.rb', content)
  358. model_attributes = Prepares.model_attributes
  359. expect(model_attributes.get_attribute_type('Post', 'title')).to eq('String')
  360. expect(model_attributes.get_attribute_type('Post', 'tags')).to eq('Array')
  361. expect(model_attributes.get_attribute_type('Post', 'comments_count')).to eq('Integer')
  362. expect(model_attributes.get_attribute_type('Post', 'deleted_at')).to eq('DateTime')
  363. expect(model_attributes.get_attribute_type('Post', 'active')).to eq('Boolean')
  364. end
  365. it 'parses mongomapper field' do
  366. content = <<-EOF
  367. class Post
  368. include MongoMapper::Document
  369. key :first_name, String
  370. key :last_name, String
  371. key :age, Integer
  372. key :born_at, Time
  373. key :active, Boolean
  374. key :fav_colors, Array
  375. end
  376. EOF
  377. runner.prepare('app/models/post.rb', content)
  378. model_attributes = Prepares.model_attributes
  379. expect(model_attributes.get_attribute_type('Post', 'first_name')).to eq('String')
  380. expect(model_attributes.get_attribute_type('Post', 'last_name')).to eq('String')
  381. expect(model_attributes.get_attribute_type('Post', 'age')).to eq('Integer')
  382. expect(model_attributes.get_attribute_type('Post', 'born_at')).to eq('Time')
  383. expect(model_attributes.get_attribute_type('Post', 'active')).to eq('Boolean')
  384. expect(model_attributes.get_attribute_type('Post', 'fav_colors')).to eq('Array')
  385. end
  386. end
  387. context 'no error' do
  388. it 'raiseds for finder_sql option' do
  389. content = <<-EOF
  390. class EventSubscription < ActiveRecord::Base
  391. has_many :event_notification_template, finder_sql: ?
  392. end
  393. EOF
  394. content =
  395. content.sub(
  396. '?',
  397. '\'SELECT event_notification_templates.* from event_notification_templates where event_type_id=#{event_type_id} and delivery_method_id=#{delivery_method_id}\''
  398. )
  399. expect { runner.prepare('app/models/event_subscription.rb', content) }.not_to raise_error
  400. end
  401. end
  402. end
  403. end
  404. end