1use std::any::type_name;
2
3use rustrails_support::inflector::{demodulize, humanize, pluralize, singularize, underscore};
4
5pub trait ModelNaming {
10 fn model_name() -> ModelName {
12 let type_name = type_name::<Self>();
13 let demodulized = demodulize(type_name);
14 ModelName::new(&demodulized)
15 }
16
17 fn model_name_instance(&self) -> ModelName {
19 Self::model_name()
20 }
21
22 fn to_model(&self) -> &Self {
24 self
25 }
26
27 fn singular(&self) -> String {
29 Self::model_name().singular
30 }
31
32 fn plural(&self) -> String {
34 Self::model_name().plural
35 }
36
37 fn route_key(&self) -> String {
39 Self::model_name().route_key
40 }
41
42 fn singular_route_key(&self) -> String {
44 Self::model_name().singular_route_key
45 }
46
47 fn param_key(&self) -> String {
49 Self::model_name().param_key
50 }
51
52 fn uncountable() -> bool {
54 let model_name = Self::model_name();
55 model_name.singular == model_name.plural
56 }
57
58 fn human_attribute_name(attribute: &str) -> String {
60 crate::naming::human_attribute_name(attribute)
61 }
62}
63
64#[derive(Debug, Clone, PartialEq, Eq)]
66pub struct ModelName {
67 pub name: String,
69 pub singular: String,
71 pub plural: String,
73 pub element: String,
75 pub collection: String,
77 pub human: String,
79 pub param_key: String,
81 pub route_key: String,
83 pub singular_route_key: String,
85 pub i18n_key: String,
87}
88
89impl ModelName {
90 pub fn new(name: &str) -> Self {
92 let underscored = underscore(name);
93 let singular = underscored.replace('/', "_");
94 let plural = pluralize(&singular);
95 let collection = pluralize(&underscored);
96 let element = underscore(&demodulize(name));
97 let human = humanize(&element);
98 let param_key = singular.clone();
99 let route_key = if singular == plural {
100 format!("{plural}_index")
101 } else {
102 plural.clone()
103 };
104 let singular_route_key = if singular == plural {
105 singular.clone()
106 } else {
107 singularize(&route_key)
108 };
109
110 Self {
111 name: name.to_string(),
112 singular,
113 plural,
114 element,
115 collection,
116 human,
117 param_key,
118 route_key,
119 singular_route_key,
120 i18n_key: underscored,
121 }
122 }
123}
124
125pub fn human_attribute_name(attribute: &str) -> String {
127 humanize(&underscore(attribute.trim()))
128}
129
130#[cfg(test)]
131mod tests {
132 use super::{ModelName, ModelNaming, human_attribute_name};
133
134 #[derive(Debug, Default)]
135 struct User;
136
137 impl ModelNaming for User {}
138
139 #[derive(Debug, Default)]
140 struct BlogPost;
141
142 impl ModelNaming for BlogPost {}
143
144 #[test]
145 fn builds_model_name_for_regular_noun() {
146 let model_name = ModelName::new("User");
147
148 assert_eq!(model_name.name, "User");
149 assert_eq!(model_name.singular, "user");
150 assert_eq!(model_name.plural, "users");
151 assert_eq!(model_name.element, "user");
152 assert_eq!(model_name.collection, "users");
153 assert_eq!(model_name.human, "User");
154 assert_eq!(model_name.param_key, "user");
155 assert_eq!(model_name.route_key, "users");
156 assert_eq!(model_name.singular_route_key, "user");
157 assert_eq!(model_name.i18n_key, "user");
158 }
159
160 #[test]
161 fn builds_model_name_for_compound_and_irregular_names() {
162 let compound = ModelName::new("BlogPost");
163 let irregular = ModelName::new("Person");
164
165 assert_eq!(compound.singular, "blog_post");
166 assert_eq!(compound.plural, "blog_posts");
167 assert_eq!(compound.human, "Blog post");
168 assert_eq!(irregular.singular, "person");
169 assert_eq!(irregular.plural, "people");
170 assert_eq!(irregular.route_key, "people");
171 }
172
173 #[test]
174 fn default_trait_model_name_uses_type_name() {
175 let user_name = User::model_name();
176 let blog_post_name = BlogPost::model_name();
177
178 assert_eq!(user_name.name, "User");
179 assert_eq!(blog_post_name.element, "blog_post");
180 assert_eq!(blog_post_name.route_key, "blog_posts");
181 }
182
183 #[test]
184 fn humanizes_attribute_names() {
185 assert_eq!(human_attribute_name("first_name"), "First name");
186 assert_eq!(User::human_attribute_name("account_id"), "Account");
187 assert_eq!(
188 BlogPost::human_attribute_name("publishedAt"),
189 "Published at"
190 );
191 }
192 #[test]
193 fn supports_namespaced_type_names() {
194 let model_name = ModelName::new("Admin::User");
195
196 assert_eq!(model_name.singular, "admin_user");
197 assert_eq!(model_name.route_key, "admin_users");
198 assert_eq!(model_name.element, "user");
199 assert_eq!(model_name.i18n_key, "admin/user");
200 }
201
202 #[test]
203 fn model_name_preserves_route_information_for_irregular_nouns() {
204 let model_name = ModelName::new("Person");
205
206 assert_eq!(model_name.param_key, "person");
207 assert_eq!(model_name.route_key, "people");
208 assert_eq!(model_name.singular_route_key, "person");
209 }
210
211 #[test]
212 fn human_attribute_name_trims_extra_whitespace() {
213 assert_eq!(human_attribute_name(" first_name "), "First name");
214 }
215
216 #[test]
217 fn model_name_human_uses_demodulized_element() {
218 let model_name = ModelName::new("Admin::BillingAddress");
219 assert_eq!(model_name.human, "Billing address");
220 }
221
222 #[test]
223 fn model_name_name_returns_the_class_name() {
224 assert_eq!(ModelName::new("User").name, "User");
225 }
226
227 #[test]
228 fn model_name_singular_returns_the_singular_form() {
229 assert_eq!(ModelName::new("User").singular, "user");
230 }
231
232 #[test]
233 fn model_name_plural_returns_the_plural_form() {
234 assert_eq!(ModelName::new("User").plural, "users");
235 }
236
237 #[test]
238 fn model_name_element_returns_the_underscored_singular_name() {
239 assert_eq!(ModelName::new("User").element, "user");
240 }
241
242 #[test]
243 fn model_name_human_returns_the_humanized_name() {
244 assert_eq!(ModelName::new("User").human, "User");
245 }
246
247 #[test]
248 fn model_name_param_key_returns_the_parameter_key() {
249 assert_eq!(ModelName::new("User").param_key, "user");
250 }
251
252 #[test]
253 fn model_name_route_key_returns_the_route_key() {
254 assert_eq!(ModelName::new("User").route_key, "users");
255 }
256
257 #[test]
258 fn model_name_singular_route_key_returns_the_singular_route_key() {
259 assert_eq!(ModelName::new("User").singular_route_key, "user");
260 }
261
262 #[test]
263 fn model_name_i18n_key_returns_the_i18n_lookup_key() {
264 assert_eq!(ModelName::new("User").i18n_key, "user");
265 }
266
267 #[test]
268 fn compound_model_name_singular_underscores_words() {
269 assert_eq!(ModelName::new("BlogPost").singular, "blog_post");
270 }
271
272 #[test]
273 fn compound_model_name_plural_pluralizes_the_underscored_name() {
274 assert_eq!(ModelName::new("BlogPost").plural, "blog_posts");
275 }
276
277 #[test]
278 fn compound_model_name_element_uses_the_demodulized_name() {
279 assert_eq!(ModelName::new("BlogPost").element, "blog_post");
280 }
281
282 #[test]
283 fn compound_model_name_human_humanizes_words() {
284 assert_eq!(ModelName::new("BlogPost").human, "Blog post");
285 }
286
287 #[test]
288 fn irregular_model_name_pluralizes_to_people() {
289 assert_eq!(ModelName::new("Person").plural, "people");
290 }
291
292 #[test]
293 fn irregular_model_name_singular_route_key_stays_person() {
294 assert_eq!(ModelName::new("Person").singular_route_key, "person");
295 }
296
297 #[test]
298 fn namespaced_model_name_singular_preserves_namespace() {
299 assert_eq!(ModelName::new("Admin::User").singular, "admin_user");
300 }
301
302 #[test]
303 fn namespaced_model_name_element_uses_the_demodulized_name() {
304 assert_eq!(ModelName::new("Admin::User").element, "user");
305 }
306
307 #[test]
308 fn namespaced_model_name_route_key_pluralizes_the_namespace_aware_key() {
309 assert_eq!(ModelName::new("Admin::User").route_key, "admin_users");
310 }
311
312 #[test]
313 fn namespaced_model_name_i18n_key_uses_slashes() {
314 assert_eq!(ModelName::new("Admin::User").i18n_key, "admin/user");
315 }
316
317 #[test]
318 fn human_attribute_name_handles_snake_case_names() {
319 assert_eq!(
320 human_attribute_name("billing_address_line"),
321 "Billing address line"
322 );
323 }
324
325 #[test]
326 fn human_attribute_name_handles_camel_case_names_with_whitespace() {
327 assert_eq!(
328 human_attribute_name(" preferredContactMethod "),
329 "Preferred contact method"
330 );
331 }
332
333 #[test]
334 fn default_trait_model_name_uses_the_type_name_for_regular_structs() {
335 #[derive(Debug, Default)]
336 struct InvoiceLine;
337
338 impl ModelNaming for InvoiceLine {}
339
340 let model_name = InvoiceLine::model_name();
341
342 assert_eq!(model_name.name, "InvoiceLine");
343 assert_eq!(model_name.element, "invoice_line");
344 }
345
346 #[test]
347 fn custom_model_name_override_can_customize_the_human_name() {
348 #[derive(Debug, Default)]
349 struct CustomerRecord;
350
351 impl ModelNaming for CustomerRecord {
352 fn model_name() -> ModelName {
353 let mut model_name = ModelName::new("User");
354 model_name.human = "Customer".to_string();
355 model_name.param_key = "customer".to_string();
356 model_name.route_key = "customers".to_string();
357 model_name.singular_route_key = "customer".to_string();
358 model_name
359 }
360 }
361
362 assert_eq!(CustomerRecord::model_name().human, "Customer");
363 }
364
365 #[test]
366 fn custom_model_name_override_can_customize_the_param_key() {
367 #[derive(Debug, Default)]
368 struct CustomerRecord;
369
370 impl ModelNaming for CustomerRecord {
371 fn model_name() -> ModelName {
372 let mut model_name = ModelName::new("User");
373 model_name.human = "Customer".to_string();
374 model_name.param_key = "customer".to_string();
375 model_name.route_key = "customers".to_string();
376 model_name.singular_route_key = "customer".to_string();
377 model_name
378 }
379 }
380
381 assert_eq!(CustomerRecord::model_name().param_key, "customer");
382 assert_eq!(CustomerRecord::model_name().route_key, "customers");
383 }
384
385 mod nested_models {
386 use super::{ModelName, ModelNaming};
387
388 #[derive(Debug, Default)]
389 pub(super) struct AuditEvent;
390
391 impl ModelNaming for AuditEvent {}
392
393 #[derive(Debug, Default)]
394 pub(super) struct BlogPostAlias;
395
396 impl ModelNaming for BlogPostAlias {
397 fn model_name() -> ModelName {
398 ModelName::new("Article")
399 }
400 }
401 }
402
403 #[test]
404 fn namespaced_compound_model_name_matches_track_back_reference() {
405 let model_name = ModelName::new("Post::TrackBack");
406
407 assert_eq!(model_name.singular, "post_track_back");
408 assert_eq!(model_name.plural, "post_track_backs");
409 assert_eq!(model_name.element, "track_back");
410 assert_eq!(model_name.human, "Track back");
411 assert_eq!(model_name.param_key, "post_track_back");
412 assert_eq!(model_name.route_key, "post_track_backs");
413 assert_eq!(model_name.i18n_key, "post/track_back");
414 }
415
416 #[test]
417 fn deeply_namespaced_irregular_model_name_pluralizes_the_final_segment() {
418 let model_name = ModelName::new("Admin::Support::Person");
419
420 assert_eq!(model_name.singular, "admin_support_person");
421 assert_eq!(model_name.element, "person");
422 assert_eq!(model_name.human, "Person");
423 assert_eq!(model_name.route_key, "admin_support_people");
424 assert_eq!(model_name.singular_route_key, "admin_support_person");
425 assert_eq!(model_name.i18n_key, "admin/support/person");
426 }
427
428 #[test]
429 fn default_trait_model_name_demodulizes_nested_type_names() {
430 let model_name = nested_models::AuditEvent::model_name();
431
432 assert_eq!(model_name.name, "AuditEvent");
433 assert_eq!(model_name.element, "audit_event");
434 assert_eq!(model_name.route_key, "audit_events");
435 assert_eq!(model_name.i18n_key, "audit_event");
436 }
437
438 #[test]
439 fn custom_model_name_override_can_replace_the_external_name() {
440 let model_name = nested_models::BlogPostAlias::model_name();
441
442 assert_eq!(model_name.name, "Article");
443 assert_eq!(model_name.singular, "article");
444 assert_eq!(model_name.element, "article");
445 assert_eq!(model_name.human, "Article");
446 assert_eq!(model_name.route_key, "articles");
447 assert_eq!(model_name.i18n_key, "article");
448 }
449
450 fn rails_track_back_model_name() -> ModelName {
451 ModelName::new("Post::TrackBack")
452 }
453
454 fn rails_isolated_blog_post_model_name() -> ModelName {
455 let mut model_name = ModelName::new("Blog::Post");
456 model_name.route_key = "posts".to_string();
457 model_name.param_key = "post".to_string();
458 model_name.singular_route_key = "post".to_string();
459 model_name
460 }
461
462 fn rails_shared_blog_post_model_name() -> ModelName {
463 ModelName::new("Blog::Post")
464 }
465
466 fn rails_supplied_article_model_name() -> ModelName {
467 ModelName::new("Article")
468 }
469
470 #[derive(Debug, Default)]
471 struct Contact;
472
473 impl ModelNaming for Contact {}
474
475 #[derive(Debug, Default)]
476 struct Sheep;
477
478 impl ModelNaming for Sheep {}
479
480 #[derive(Debug, Default)]
481 struct RelativeBlogPost;
482
483 impl ModelNaming for RelativeBlogPost {
484 fn model_name() -> ModelName {
485 rails_isolated_blog_post_model_name()
486 }
487 }
488
489 #[test]
490 fn test_rails_track_back_singular() {
491 assert_eq!(rails_track_back_model_name().singular, "post_track_back");
492 }
493
494 #[test]
495 fn test_rails_track_back_plural() {
496 assert_eq!(rails_track_back_model_name().plural, "post_track_backs");
497 }
498
499 #[test]
500 fn test_rails_track_back_element() {
501 assert_eq!(rails_track_back_model_name().element, "track_back");
502 }
503
504 #[test]
505 fn test_rails_track_back_collection() {
506 assert_eq!(rails_track_back_model_name().collection, "post/track_backs");
507 }
508
509 #[test]
510 fn test_rails_track_back_human() {
511 assert_eq!(rails_track_back_model_name().human, "Track back");
512 }
513
514 #[test]
515 fn test_rails_track_back_route_key() {
516 assert_eq!(rails_track_back_model_name().route_key, "post_track_backs");
517 }
518
519 #[test]
520 fn test_rails_track_back_param_key() {
521 assert_eq!(rails_track_back_model_name().param_key, "post_track_back");
522 }
523
524 #[test]
525 fn test_rails_track_back_i18n_key() {
526 assert_eq!(rails_track_back_model_name().i18n_key, "post/track_back");
527 }
528
529 #[test]
530 fn test_rails_track_back_is_not_uncountable() {
531 let model_name = rails_track_back_model_name();
532 assert_ne!(model_name.singular, model_name.plural);
533 }
534
535 #[test]
536 fn test_rails_namespaced_model_in_isolated_namespace_singular() {
537 assert_eq!(rails_isolated_blog_post_model_name().singular, "blog_post");
538 }
539
540 #[test]
541 fn test_rails_namespaced_model_in_isolated_namespace_plural() {
542 assert_eq!(rails_isolated_blog_post_model_name().plural, "blog_posts");
543 }
544
545 #[test]
546 fn test_rails_namespaced_model_in_isolated_namespace_element() {
547 assert_eq!(rails_isolated_blog_post_model_name().element, "post");
548 }
549
550 #[test]
551 fn test_rails_namespaced_model_in_isolated_namespace_collection() {
552 assert_eq!(
553 rails_isolated_blog_post_model_name().collection,
554 "blog/posts"
555 );
556 }
557
558 #[test]
559 fn test_rails_namespaced_model_in_isolated_namespace_human() {
560 assert_eq!(rails_isolated_blog_post_model_name().human, "Post");
561 }
562
563 #[test]
564 fn test_rails_namespaced_model_in_isolated_namespace_route_key() {
565 assert_eq!(rails_isolated_blog_post_model_name().route_key, "posts");
566 }
567
568 #[test]
569 fn test_rails_namespaced_model_in_isolated_namespace_param_key() {
570 assert_eq!(rails_isolated_blog_post_model_name().param_key, "post");
571 }
572
573 #[test]
574 fn test_rails_namespaced_model_in_isolated_namespace_i18n_key() {
575 assert_eq!(rails_isolated_blog_post_model_name().i18n_key, "blog/post");
576 }
577
578 #[test]
579 fn test_rails_namespaced_model_in_shared_namespace_singular() {
580 assert_eq!(rails_shared_blog_post_model_name().singular, "blog_post");
581 }
582
583 #[test]
584 fn test_rails_namespaced_model_in_shared_namespace_plural() {
585 assert_eq!(rails_shared_blog_post_model_name().plural, "blog_posts");
586 }
587
588 #[test]
589 fn test_rails_namespaced_model_in_shared_namespace_element() {
590 assert_eq!(rails_shared_blog_post_model_name().element, "post");
591 }
592
593 #[test]
594 fn test_rails_namespaced_model_in_shared_namespace_collection() {
595 assert_eq!(rails_shared_blog_post_model_name().collection, "blog/posts");
596 }
597
598 #[test]
599 fn test_rails_namespaced_model_in_shared_namespace_human() {
600 assert_eq!(rails_shared_blog_post_model_name().human, "Post");
601 }
602
603 #[test]
604 fn test_rails_namespaced_model_in_shared_namespace_route_key() {
605 assert_eq!(rails_shared_blog_post_model_name().route_key, "blog_posts");
606 }
607
608 #[test]
609 fn test_rails_namespaced_model_in_shared_namespace_param_key() {
610 assert_eq!(rails_shared_blog_post_model_name().param_key, "blog_post");
611 }
612
613 #[test]
614 fn test_rails_namespaced_model_in_shared_namespace_i18n_key() {
615 assert_eq!(rails_shared_blog_post_model_name().i18n_key, "blog/post");
616 }
617
618 #[test]
619 fn test_rails_supplied_model_name_singular() {
620 assert_eq!(rails_supplied_article_model_name().singular, "article");
621 }
622
623 #[test]
624 fn test_rails_supplied_model_name_plural() {
625 assert_eq!(rails_supplied_article_model_name().plural, "articles");
626 }
627
628 #[test]
629 fn test_rails_supplied_model_name_element() {
630 assert_eq!(rails_supplied_article_model_name().element, "article");
631 }
632
633 #[test]
634 fn test_rails_supplied_model_name_collection() {
635 assert_eq!(rails_supplied_article_model_name().collection, "articles");
636 }
637
638 #[test]
639 fn test_rails_supplied_model_name_human() {
640 assert_eq!(rails_supplied_article_model_name().human, "Article");
641 }
642
643 #[test]
644 fn test_rails_supplied_model_name_route_key() {
645 assert_eq!(rails_supplied_article_model_name().route_key, "articles");
646 }
647
648 #[test]
649 fn test_rails_supplied_model_name_param_key() {
650 assert_eq!(rails_supplied_article_model_name().param_key, "article");
651 }
652
653 #[test]
654 fn test_rails_supplied_model_name_i18n_key() {
655 assert_eq!(rails_supplied_article_model_name().i18n_key, "article");
656 }
657
658 #[test]
659 fn test_rails_supplied_locale_singular() {
660 assert_eq!(ModelName::new("Uzivatel").singular, "uzivatel");
661 }
662
663 #[test]
664 #[ignore = "Rails-specific: ModelName::new has no locale-specific inflection support"]
665 fn test_rails_supplied_locale_plural() {}
666
667 #[test]
668 fn test_rails_relative_model_name_singular() {
669 assert_eq!(RelativeBlogPost::model_name().singular, "blog_post");
670 }
671
672 #[test]
673 fn test_rails_relative_model_name_plural() {
674 assert_eq!(RelativeBlogPost::model_name().plural, "blog_posts");
675 }
676
677 #[test]
678 fn test_rails_relative_model_name_element() {
679 assert_eq!(RelativeBlogPost::model_name().element, "post");
680 }
681
682 #[test]
683 fn test_rails_relative_model_name_collection() {
684 assert_eq!(RelativeBlogPost::model_name().collection, "blog/posts");
685 }
686
687 #[test]
688 fn test_rails_relative_model_name_human() {
689 assert_eq!(RelativeBlogPost::model_name().human, "Post");
690 }
691
692 #[test]
693 fn test_rails_relative_model_name_route_key() {
694 assert_eq!(RelativeBlogPost::model_name().route_key, "posts");
695 }
696
697 #[test]
698 fn test_rails_relative_model_name_param_key() {
699 assert_eq!(RelativeBlogPost::model_name().param_key, "post");
700 }
701
702 #[test]
703 fn test_rails_relative_model_name_i18n_key() {
704 assert_eq!(RelativeBlogPost::model_name().i18n_key, "blog/post");
705 }
706
707 #[test]
708 fn test_rails_naming_helpers_to_model_called_on_record() {
709 let contact = Contact;
710 assert_eq!(contact.to_model().param_key(), "contact");
711 }
712
713 #[test]
714 fn test_rails_naming_helpers_singular_for_record() {
715 let contact = Contact;
716 assert_eq!(contact.singular(), "contact");
717 }
718
719 #[test]
720 fn test_rails_naming_helpers_singular_for_class() {
721 assert_eq!(Contact::model_name().singular, "contact");
722 }
723
724 #[test]
725 fn test_rails_naming_helpers_plural_for_record() {
726 let contact = Contact;
727 assert_eq!(contact.plural(), "contacts");
728 }
729
730 #[test]
731 fn test_rails_naming_helpers_plural_for_class() {
732 assert_eq!(Contact::model_name().plural, "contacts");
733 }
734
735 #[test]
736 fn test_rails_naming_helpers_route_key_for_record() {
737 let contact = Contact;
738 assert_eq!(contact.route_key(), "contacts");
739 assert_eq!(contact.singular_route_key(), "contact");
740 }
741
742 #[test]
743 fn test_rails_naming_helpers_route_key_for_class() {
744 let model_name = Contact::model_name();
745 assert_eq!(model_name.route_key, "contacts");
746 assert_eq!(model_name.singular_route_key, "contact");
747 }
748
749 #[test]
750 fn test_rails_naming_helpers_param_key_for_record() {
751 let contact = Contact;
752 assert_eq!(contact.param_key(), "contact");
753 }
754
755 #[test]
756 fn test_rails_naming_helpers_param_key_for_class() {
757 assert_eq!(Contact::model_name().param_key, "contact");
758 }
759
760 #[test]
761 fn test_rails_naming_helpers_uncountable() {
762 let sheep_name = Sheep::model_name();
763 let contact_name = Contact::model_name();
764
765 assert_eq!(sheep_name.singular, "sheep");
766 assert_eq!(sheep_name.plural, "sheep");
767 assert_ne!(contact_name.singular, contact_name.plural);
768 }
769
770 #[test]
771 fn test_rails_naming_helpers_uncountable_route_key() {
772 let sheep_name = Sheep::model_name();
773 assert_eq!(sheep_name.singular_route_key, "sheep");
774 assert_eq!(sheep_name.route_key, "sheep_index");
775 assert!(Sheep::uncountable());
776 }
777
778 #[test]
779 #[ignore = "Rails-specific: Rust types are always named and ModelName::new requires an explicit name"]
780 fn test_rails_anonymous_class_without_name_argument() {}
781
782 #[test]
783 fn test_rails_anonymous_class_with_name_argument() {
784 assert_eq!(ModelName::new("Anonymous").name, "Anonymous");
785 }
786
787 #[test]
788 fn test_rails_model_name_method_delegation() {
789 let contact = Contact;
790 assert_eq!(contact.model_name_instance(), Contact::model_name());
791 }
792
793 #[test]
794 fn test_rails_overriding_accessors_keys_for_supported_fields() {
795 let mut model_name = rails_track_back_model_name();
796 model_name.singular = "singular".to_string();
797 model_name.plural = "plural".to_string();
798 model_name.element = "element".to_string();
799 model_name.collection = "collection".to_string();
800 model_name.singular_route_key = "singular_route_key".to_string();
801 model_name.route_key = "route_key".to_string();
802 model_name.param_key = "param_key".to_string();
803 model_name.i18n_key = "i18n_key".to_string();
804 model_name.name = "name".to_string();
805
806 assert_eq!(model_name.singular, "singular");
807 assert_eq!(model_name.plural, "plural");
808 assert_eq!(model_name.element, "element");
809 assert_eq!(model_name.collection, "collection");
810 assert_eq!(model_name.singular_route_key, "singular_route_key");
811 assert_eq!(model_name.route_key, "route_key");
812 assert_eq!(model_name.param_key, "param_key");
813 assert_eq!(model_name.i18n_key, "i18n_key");
814 assert_eq!(model_name.name, "name");
815 }
816
817 #[test]
818 fn test_rails_overriding_accessors_collection_key() {
819 let mut model_name = rails_track_back_model_name();
820 model_name.collection = "custom/collection".to_string();
821 assert_eq!(model_name.collection, "custom/collection");
822 }
823
824 #[test]
825 fn test_rails_anonymous_class_with_name_argument_uses_the_supplied_name_for_metadata() {
826 let model_name = ModelName::new("Anonymous");
827
828 assert_eq!(model_name.name, "Anonymous");
829 assert_eq!(model_name.singular, "anonymous");
830 assert_eq!(model_name.element, "anonymous");
831 assert_eq!(model_name.human, "Anonymous");
832 assert_eq!(model_name.param_key, "anonymous");
833 assert_eq!(model_name.i18n_key, "anonymous");
834 }
835}