I am new to Ruby on Rails. So far, I have only created CRUD operations by using scaffolding. Now, I need to integrate two entities into single form using scaffolding, not by hard coding it.
How can we scaffold two entities together using script?
I have two entities, Student_address and Student_phnumber. I want to scaffold these two entities into a single form where I can do CRUD operations, and I want to achieve this by scaffolding.
Student_address is an entity consisting of Hse_name, Street_name, etc.
Student_phnumber another entity consisting of ph_number, type, etc.
I want to scaffold these two entities together.
Scaffolding is nothing more than a generator set up to model a complete basic resource. There are many other generators, other than scaffolding, that come with Rails by default. None of them are set up to generate resources for a set of related models. I suspect that a large part of this is because of the wide range of methods to express such a relationship make creating a generic UI virtually impossible. Also, scaffolding is more set up to get you up and running very quickly, with the intention of being modified to suit your needs. These modifications are usually fairly involved for any non-trivial application. There are many 3rd party generators out there, including the popular nifty generators, but none that create the kind of code you want to generate, as far as I know. If this is a relationship that you need to set up frequently, you may consider creating a generator of your own to handle the task - it's actually pretty easy. A good way to do it is to implement your ideal case, then create a generator from it.
Edit:
Also, you may wish to adjust your variable/attribute names. They should be lowercase and underscored, so Street_name would become street_name. Arbitrary abbreviations also make it very hard to code/maintain, so Student_phnumber would be better expressed as student_phone_number. The reason for doing this, apart from consistency (ph_number vs Student_phnumber, for example), is that Rails actually uses the casing and spacing in internal methods like these.
Let me see if I understand you.
The model/entity relationship you are describing is:
student
address
- house_name
- street_name
- etc
phone_number
- number
- area_code
- etc
You want to:
a) automatically generate the models
b) automatically generate a controller/view with a form to create a student, including fields to set up the address and phone number
Okay. b) can't be done via a Rails scaffold. You can, however, use the ActiveSupport gem (docs here) to achieve this. Here's what you do:
gem install active_scaffold
rails g active_scaffold Student name:string
rails g active_scaffold PhoneNumber area_code:integer number:integer student_id:integer
rails g active_scaffold Address first_line:string second_line:string student_id:integer
The only manual work you'll have to do here is pop into the models and add the relationships:
Address
belongs_to :student
PhoneNumber
belongs_to :student
Student
has_one :address
has_one :phone_number
What ActiveScaffold will do is automatically produce for you a view like this:
Fill in that form and your models will all be saved and linked together!
Is this what you are looking for?
rails generate scaffold Student student_address:string student_phnumber:string
Related
I'm starting out with ruby and rails, it's my 1st day, reading the guides.
I'm trying to generate a scaffold with various models, for instance Game and Platform. I'm trying to replace an existing, way outdated Symfony PHP project and picked Ruby/RoR for learning purposes, also because I was impressed with hotwire from the blog demo video.
A Game has_one Platform, a Platform has_many Games.
Or
type Game {
id: ID!
name: String
slug: String
platform: Platform!
}
type Platform {
id: ID!
name: String
slug: String
games: [Game]
}
For now I'd like to generate those 2 models with "rails g scaffold". I read on other questions that one has to use ":references" but I can't find that keyword anywhere in any guide of activerecord.
rails g scaffold Game name:string slug:string platform:references
is what I have so far. Is it even possible to define associations with foreign keys via the cli?
What is the typical workflow when generating models/scaffolds? Do you just start with the bare minimum of the model and manually edit the migration, add fk and associations?
I guess I'm more looking for a discord server for ruby/rails/other. I have so many questions but don't feel like this belongs here, because I would create question after question. But for now let's stick to this. (Side question, what is the de-facto standard when it comes to authn/z in rails? And another question, is there somelike that auto-slugifies, see the name and slug connection?)
The question is how to express model associations on the command line?
Is it even possible to define associations with foreign keys via the cli?
Yes.
You can define belongs_to assocations via the generators - as its the only assocation thats actually backed by a database column on this models table. You cannot define has_one, has_many or has_and_belongs_belongs_to_many via the generators - they must be added to the model later.
For now I'd like to generate those 2 models with "rails g scaffold". I read on other questions that one has to use ":references" but I can't find that keyword anywhere in any guide of activerecord.
It is not really a keyword. Rather references/belongs_to (the later is an alias) are column types (well kind of) when generating models or migrations.
If you run rails g model -h it details the options:
You can also consider references as a kind of type. For instance, if
you run:
bin/rails generate model photo title:string album:references
It will generate an album_id column. You should generate these kinds
of fields when you will use a belongs_to association, for instance.
It also adds belongs_to :album in the model when you use it with the model generator.
What is the typical workflow when generating models/scaffolds? Do you just start with the bare minimum of the model and manually edit the migration, add fk and associations?
Scaffolds are mainly useful for rapid prototyping or when you're learning as way to see the "Rails Way" of defining resources. They tend to generate way more code then you actually need and will outrun your tests.
Generators in general are just a tool and its often easier and faster to just edit the resulting files then to get the exact invokation of the generator right.
I have a database with several tables, each one containing columns that may not follow the rails naming convention.
Is there a tool existing to create the ActiveRecord models from those tables or do I need to do this at hand, one by one ?
If I create the ActiveRecord model for one table by hand, would this be ok though ? (no hidden DB identifier needed on top of it ?)
UPDATE
I have tried magicmodels but cannot have it working (it has been a while since it was last modified) and does not seem to be compatible with rails 3.2
What I tried then:
- change the database.yml so it points towards my existing Postresql database
- manually create my models such as:
# app/models/user.rb
class User < ActiveRecord::Base
end
- run the console and tried
User.all
=> I end up with an error saying that contant User was not initialized.
Doesn't the console import the model automatically ? Or is that linked to the fact the configuration I did is not correct ?
http://magicmodels.rubyforge.org/magic_model_generator/ may be what you're looking for. I haven't heard of many tools that give this functionality, though, as many rails apps are designed from scratch instead of given a legacy db and then creating the models from that.
You can easily create models by hand and map them to pretty much any db table. Models have a "set_table_name 'name'" that lets you over-write the rails default convention of a single model mapping to a plural db table name.
ActiveRecord works OK with legacy databases. I did a back-end system that didn't use Rails with ActiveRecord as my ORM. "ActiveRecord Without Rails" got me started. "Using ActiveRecord outside Rails" is also useful. Search Google for "use activerecord without rails" and you'll find even more.
You don't need a fully fleshed out model. Just use a base class for the tables you want and ActiveRecord will query the database for what it needs. It won't know about table relationships, but for general queries it'll do fine. Build the relationships as you go and need them.
All of the tutorials I've seen so far for RoR have shown me generating models like:
rails generate User name:string placeofbirth:string
This generates a class for the model, and only actually references an attribute if I apply a validation of some kind.
So my question is, how do I use a 'code' first approach when creating my models. Or is it the rails way to just right down on paper the attributes you want, run the generate command with each attribute you want and it's type, then run the rake db:migrate command?
I'd love some more proven patterns on this subject because so far the way I've seen seems too empty.
Yes, this is the rails way- migration comes first and generates the code and the database- and the model class inspects the database to see what fields are there and make accessible via methods.
You can do gem install annotate_models if you want to get some comments in your model class with the attribute names and types.
See here for an example: https://github.com/ctran/annotate_models
Rails uses an active record pattern for models which basically means that a model object will automatically map each DB column to an attribute so you don't have to specify all attributes in the model. It's a feature, but I agree that it might not be perfect for everyone. If you're using Rails 3 it should be easy to use another ORM of your choice if ActiveRecord's approach doesn't suit you. Here are some alternative ORMs that you could use.
Usually when you are developing some database backed web application, you know the database design(name of the tables, name of the columns in those tables and associations between different tables) beforehand.
Rails, as mentioned by maarons in his answer, uses Active Record pattern. Your models are classes that represent a table in your database, an instance of your model class a row in that table and different attributes of an object represent values under different columns in the same table.
When you create a model, usually, you are creating a class that represents one of the tables in your database. And while you are creating a model, you are also going to create a table in your database. That means knowing the name of the table and columns within that table.
So to answer your question, you must know all the columns, required for the time being, that will be in your tables. And hence available as attribute methods for your model objects. You specify these columns to added in the table in the migration generated by rails generator while generating this model. This is what usually everyone does.
You can take a code first approach by creating a class, without running the rails model generator,under app/models/ but not inheriting it from ActiveRecord::Base. As you move forward in your development, you can generate migrations by $ rails generate migration MigrationName and creating table and adding columns using [add_column][2]to that table as required. Once you have created a table for this model, you will have to inherit that model from ActiveRecord::Base so that you can get all the Rails magic in your application.
I'm working through the Ruby on Rails tutorial and just made a Comment model with three properties.
rails generate model Comment commenter:string body:text post:references
It generated an ActiveRecord class with post but not commenter and body.
class Comment < ActiveRecord::Base
belongs_to :post
end
Why doesn't rails formally define the non-reference properties anywhere other than the DB migration scripts?
Rails dynamically loads attributes - specifically, the names of the columns and their types - based on the database schema. There is no need to define or declare them in your models. For apps running in production, it does this once, at load time. For development, it will reload them as often as every request, but only loads them when each model is used.
Rails does not infer other things from your database, though. For instance, if you were to place a unique index on a name column, it would not automatically add a validates_uniqueness_of :name to your model. Of course, the database would still enforce this constraint when you save the record, causing an exception to be raised should the name field contain a duplicate value. The recommendation, in this case, is to do both.
Why doesn't rails formally define the non-reference properties anywhere other than the DB migration scripts?
Well, where do you need them "defined" anyways? Migrations are the only place where these attributes matter coz its responsibility is to create database tables with those attributes.
If you do a scaffold on comments with similar parameters, it would also generate the views and it would be using the attributes. They don't need to be "defined" as such anywhere else.
The short answer to your question is "no". Even the migration is not a definitive place to look as there might be many migrations related to a model.
However, you may have a look at the generated "db/schema.rb" which is an aggregation of all migrations. It contains the schema definition of all activerecord models. This maybe your best bet.
Additionally, you may want to use the https://github.com/ctran/annotate_models plugin that inserts a comment in your model to help you keep track of all your model's attributes.
I'm designing a ruby on rails app for a pharmacy, and one of the features is that there are stores who have pharmacists who work there. In addition, there are pharmacists, who can work at many stores. This sounds like a job for HABTM, right? Well, being the novice I am, I manually designed a workaround (because I never heard of HABTM - I basically taught myself rails and never got to some of the more advanced relationships). Right now, when a pharmacist is saved, there's a couple of lines in the create and update action of the pharmacists controller that turns the stores that they work at into a string, with each store_id separated by a comma. Then, when a store is displayed, it does a MYSQL request by
#pharmacists = Pharmacist.find :all, :conditions => "stores REGEXP '#{#store.id}'"
Would moving this system over to a rails based HABTM system be more efficient? Of course it would require less code in the end, but would it be worth it? In other words, what benefits, other than less code, would I get from moving this association to be managed by rails?
The benefit is that you will be using the right tool for the job! The whole point of using a framework such as Rails is that it helps you solve common problems without having to re-invent the wheel, which is what you've done here. By using associations you'll also be using a relational database properly and can take advantage of benefits like foreign key indexing, which will be faster than string manipulation.
You should use a has_and_belongs_to_many relationship unless you need to store extra attributes on the join model (for example the date a pharmacist started working at a store) in which case use has_many :through.
Using Rails associations will give you all the convenient methods that Rails provides, such as these:
# Find the stores the first pharmacist works at
#stores = Pharmacist.first.stores
# Find the pharmacists who work at a store
#pharmacists = Store.find_by_name('A Store').pharmacists
A Guide to ActiveRecord Associations