Rails 3 关系模型的脚手架

发布于 2024-10-25 10:23:38 字数 31 浏览 6 评论 0原文

是否有任何教程如何构建使用多对多关系的简单模型?

are there any tutorials out there how to scaffolding a simple model that uses many-to-many relationships?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

も让我眼熟你 2024-11-01 10:23:38

这是我在 Rails 3.0.5 上使用 ruby​​ 1.9.2 逐步创建以下测试应用程序时编写的。另请参阅“Gemfile”了解我使用的 gem(整个 Testapp 可下载,链接位于第 15 部分的末尾)。所以这里是:

1)转到您想要创建测试应用程序的地方,然后

rails new mynewtestapp
cd mynewtestapp

2)然后添加 2 个具有 has_and_belongs_to_many 关联的模型

rails g scaffold book title:string author:string
rails g scaffold user name:string age:integer

3)然后您需要为该关联创建连接表...默认情况下Rails 将查找一个表,该表的名称由两个关联表(按字母顺序排列)的名称组成...因此,让我们创建一个迁移来创建这样一个表

rails g migration createBooksUsers

4) 打开生成的迁移文件,此时看起来像

class CreateBooksUsers < ActiveRecord::Migration
  def self.up
  end

  def self.down
  end
end

5) 修改该文件看起来像这样

class CreateBooksUsers < ActiveRecord::Migration
  def self.up
    create_table :books_users, :id => false do |t|
      t.integer :book_id
      t.integer :user_id
    end
  end

  def self.down
    drop_table :books_users
  end
end

6) 将 has_and_belongs_to_many 关联添加到书籍和用户模型,以及关系

app/model/book.rb

class Book < ActiveRecord::Base
  attr_accessible :title, :author, :user_ids
  has_and_belongs_to_many :users
end

添加的新 id app/model/user.rb

class User < ActiveRecord::Base
  attr_accessible: :name, :age, :book_ids
  has_and_belongs_to_many :books
end

7) 现在我们的模型和迁移已完成...让我们创建表

rake db:create
rake db:migrate

(如果您使用 sqlite3 或者如果您已创建要手动使用的数据库,那么创建可能不是必需的,此示例将使用 sqlite 工作,因此我没有添加与安装数据库管理相关的任何内容-但由于有很多,而且实际上所有值得使用的东西都有很好的文档,您很快就会找到有关该问题的任何帮助)

8)现在决定将哪个对象分配给哪个对象......当然您可以两种方法都可以...我会保持简单并向一个人演示...假设您只有几个用户并希望将这些用户分配给书籍...

在这一点上,我想说让我们得到一些外部帮助,如二进制 x 建议...但为了简单起见,我会选择 simple_form gem 而不是 Formtastic。我想每个人都有自己的最爱...但是 simple_form 似乎给了你更多的自由,可以根据你的意愿对整个输出进行 css 样式设置...所以让我们在这一点上安装 simple_form,只需将

echo "gem 'simple_form', :git => 'git://github.com/plataformatec/simple_form.git'" >> Gemfile

simple_form 添加到你的 Gemfile 中,然后运行

bundle install

并在 9) 之前将简单表单​​安装到您的应用程序中(即生成配置、默认样式和语言文件),

rails g simple_form:install

然后修改我们的图书表单

现在的图书表单应该如下所示

app/views/books/_form.html.erb

01    <%= form_for(@book) do |f| %>
02      <% if @book.errors.any? %>
03        <div id="error_explanation">
04          <h2><%= pluralize(@book.errors.count, "error") %> prohibited this book from being saved:</h2>
05    
06          <ul>
07          <% @book.errors.full_messages.each do |msg| %>
08            <li><%= msg %></li>
09          <% end %>
10          </ul>
11        </div>
12      <% end %>
13    
14      <div class="field">
15        <%= f.label :title %><br />
16        <%= f.text_field :title %>
17      </div>
18      <div class="field">
19        <%= f.label :author %><br />
20        <%= f.text_field :author %>
21      </div>
22      <div class="actions">
23        <%= f.submit %>
24      </div>
25    <% end %>

使用 simple_form,我们只需替换上面的一些代码(第 1 行和第 14 - 24 行),整个文件将如下所示:

01    <%= simple_form_for(@book) do |f| %>
02      <% if @book.errors.any? %>
03        <div id="error_explanation">
04          <h2><%= pluralize(@book.errors.count, "error") %> prohibited this book from being saved:</h2>
05    
06          <ul>
07          <% @book.errors.full_messages.each do |msg| %>
08            <li><%= msg %></li>
09          <% end %>
10          </ul>
11        </div>
12      <% end %>
13    
14      <%= f.input :title %>
15      <%= f.input :author %>
16      <%= f.association :users %>
17    
18      <%= f.button :submit %>
19    
20    <% end %>

10) 现在您可能想要启动应用程序

rails s

,添加一些用户,然后添加一本书,然后就有您的第一个 has_and_belongs_to_many形式:
first simple_form form without特效

11) 好吧,这可能还不是最漂亮的东西,但只是一个简单的添加样式表会有所帮助...创建一个新文件

public/stylesheets/simple_form.css

并将以下行粘贴到其中

/* public/stylesheets/simple_form.css */
.simple_form label {
  float: left;
  width: 100px;
  text-align: right;
  margin: 2px 10px;
}

.simple_form div.input {
  margin-bottom: 10px;
}

.simple_form div.boolean, .simple_form input[type='submit'] {
  margin-left: 120px;
}

.simple_form div.boolean label, .simple_form label.collection_radio, .simple_form label.collection_check_boxes{
  float: none;
  margin: 0;
}

.simple_form .error {
  clear: left;
  margin-left: 120px;
  font-size: 12px;
  color: #D00;
  display: block;
}

.simple_form .hint {
  clear: left;
  margin-left: 120px;
  font-size: 12px;
  color: #555;
  display: block;
  font-style: italic;
}

然后重新加载页面并... Tadaa ...先攻...
添加默认的 simple_form 样式表后

12) 如果您不喜欢多项选择列表框,请返回书籍形成

app/views/books/_form.html.erb

修改行

15      <%= f.input :author %>

并稍微

15      <%= f.input :author, :as => :check_boxes %>

以在列表框中添加复选框....但是... ewww.... 看看这个:
从左到右复选框显示

13) 似乎有点不对...从左到右显示选项会带来麻烦simple_form 新手时不时地出现,但实际上它是一个很容易解决的问题

,除了那个小格式问题之外,您可能还想看到他的名字后面的用户年龄(用大括号括起来),例如“Tom(25)”

......所以让我们做 3 个快速修复

a) 在 config/initializers/simple_form.rb 中取消注释并设置 2 个选项,以便用 div 包装每个复选框并将复选框集放置在字段集中

  # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
  config.collection_wrapper_tag = :fieldset

  # You can wrap each item in a collection of radio/check boxes with a tag, defaulting to none.
  config.item_wrapper_tag = :div

b) 稍微修改我们的 simple_form.css 样式表,如添加:

fieldset { border: 0; }

...除非您希望字段集周围有一个丑陋的大边框

c)在我们的用户模型中创建方法“to_label”,因为“to_label”默认是 simple_form 寻找的第一个方法,以便获得用于显示对象的字符串表示形式。由于一个奇怪的事件,我们的模型用户有一个名为“名称”的列。由于 name 也是 simple_form 在模型中查找的方法,我们很幸运这个应用程序到目前为止一直有效。如果我们将名称列称为 forename,Rails 将不会列出用户名,而是列出默认的 ruby​​ 对象表示形式(例如 <#User:521369846>)。我想我们很幸运;-)

app/models/user.rb

class User < ActiveRecord::Base
  has_and_belongs_to_many :users

  def to_label
    "#{name} (#{age})"
  end

end

并且编辑表单看起来很漂亮......
nice and cosy edit view

14) 现在只有显示视图需要显示图书所有者...这也不太难,只需打开 show-view

app/views/books/show.html.erb

并添加第 13-16 行以显示书主:

01    <p id="notice"><%= notice %></p>
02    
03    <p>
04      <b>Title:</b>
05      <%= @book.title %>
06    </p>
07    
08    <p>
09      <b>Author:</b>
10      <%= @book.author %>
11    </p>
12    
13    <p>
14      <b>Who owns a copy?</b>
15      <%= @book.users.map {|x| x.to_label}.join ', ' %>
16    </p>
17    
18    <%= link_to 'Edit', edit_book_path(@book) %> |
19    <%= link_to 'Back', books_path %>

最后但并非最不重要的......显示视图
谁拥有一本书?

15) 好了,关于 habtm 的快速教程就到此为止,或者换句话说,rails 中的 has_and_belongs_to_many 关联。我已将我在网上编写本文时创建的测试应用程序放在
https://1drv.ms/u/s!Alpu50oGtUZq7AiJkL08QqBiMAjb

This tut i have written while creating the below testapp step by step using ruby 1.9.2 on Rails 3.0.5. Also see 'Gemfile' for the gems I used (whole Testapp downloadable, link is at the end in part 15). So here goes:

1) go to a place where you want to create a test app, then

rails new mynewtestapp
cd mynewtestapp

2) then add 2 models that have a has_and_belongs_to_many association

rails g scaffold book title:string author:string
rails g scaffold user name:string age:integer

3) then you need to create the join-table for that asssociation... by default rails will look for a table with the name consisting of the names both associated tables in alphabetical order... so lets create a migration to create such a table

rails g migration createBooksUsers

4) open the generated migration file, which at that point looks like

class CreateBooksUsers < ActiveRecord::Migration
  def self.up
  end

  def self.down
  end
end

5) modify that to look like this

class CreateBooksUsers < ActiveRecord::Migration
  def self.up
    create_table :books_users, :id => false do |t|
      t.integer :book_id
      t.integer :user_id
    end
  end

  def self.down
    drop_table :books_users
  end
end

6) add the has_and_belongs_to_many association to the book and user models, as well as the new ids added by the relationship

app/model/book.rb

class Book < ActiveRecord::Base
  attr_accessible :title, :author, :user_ids
  has_and_belongs_to_many :users
end

app/model/user.rb

class User < ActiveRecord::Base
  attr_accessible: :name, :age, :book_ids
  has_and_belongs_to_many :books
end

7) now our models and migrations are done ... lets create the tables

rake db:create
rake db:migrate

(well create might not be necessary if you use sqlite3 or if you have created the database to be used manually, this example will work using sqlite therfore i have not added anything related to installing a database-management-system. but as there are plenty and actually all worthy enough to be used are very well documented, you will find any help about that pretty quick)

8) now decide which object shall be assigned to which object.... of course you can do that both ways... i'll keep it simple and demonstrate that to one... lets say you have only a few users and want to assign those to the books...

at this point, i would say lets get some outside help, like binary x suggested... but for simplicity i'd choose the simple_form gem over Formtastic. I guess everyone has their favorites... but simple_form seems to give you more freedom in css-styling the whole output to your wishes... so lets install simple_form at this point, just do

echo "gem 'simple_form', :git => 'git://github.com/plataformatec/simple_form.git'" >> Gemfile

to add simple_form to your Gemfile, then run

bundle install

and install simple form to your application (i. e. generate config, default styles and language files) by

rails g simple_form:install

9) time to modify our books form

the books form right now should look like this

app/views/books/_form.html.erb

01    <%= form_for(@book) do |f| %>
02      <% if @book.errors.any? %>
03        <div id="error_explanation">
04          <h2><%= pluralize(@book.errors.count, "error") %> prohibited this book from being saved:</h2>
05    
06          <ul>
07          <% @book.errors.full_messages.each do |msg| %>
08            <li><%= msg %></li>
09          <% end %>
10          </ul>
11        </div>
12      <% end %>
13    
14      <div class="field">
15        <%= f.label :title %><br />
16        <%= f.text_field :title %>
17      </div>
18      <div class="field">
19        <%= f.label :author %><br />
20        <%= f.text_field :author %>
21      </div>
22      <div class="actions">
23        <%= f.submit %>
24      </div>
25    <% end %>

Using simple_form, we can just replace some of the above code (lines 1 and 14 - 24) so the whole file would look like this:

01    <%= simple_form_for(@book) do |f| %>
02      <% if @book.errors.any? %>
03        <div id="error_explanation">
04          <h2><%= pluralize(@book.errors.count, "error") %> prohibited this book from being saved:</h2>
05    
06          <ul>
07          <% @book.errors.full_messages.each do |msg| %>
08            <li><%= msg %></li>
09          <% end %>
10          </ul>
11        </div>
12      <% end %>
13    
14      <%= f.input :title %>
15      <%= f.input :author %>
16      <%= f.association :users %>
17    
18      <%= f.button :submit %>
19    
20    <% end %>

10) Now you may want to start your application

rails s

add some users, then add a book and and there is your first has_and_belongs_to_many form:
first simple_form form without special effects

11) Well that might not yet be the most beautiful thing to look at, but a simple addition of a stylesheet will help a bit... create a new file

public/stylesheets/simple_form.css

and paste the following lines into it

/* public/stylesheets/simple_form.css */
.simple_form label {
  float: left;
  width: 100px;
  text-align: right;
  margin: 2px 10px;
}

.simple_form div.input {
  margin-bottom: 10px;
}

.simple_form div.boolean, .simple_form input[type='submit'] {
  margin-left: 120px;
}

.simple_form div.boolean label, .simple_form label.collection_radio, .simple_form label.collection_check_boxes{
  float: none;
  margin: 0;
}

.simple_form .error {
  clear: left;
  margin-left: 120px;
  font-size: 12px;
  color: #D00;
  display: block;
}

.simple_form .hint {
  clear: left;
  margin-left: 120px;
  font-size: 12px;
  color: #555;
  display: block;
  font-style: italic;
}

Then reload the page and ... Tadaa ... first strike...
after adding a default simple_form stylesheet

12) And if you don't like multiple-choice-listboxes just go back to the books form

app/views/books/_form.html.erb

and modify line

15      <%= f.input :author %>

slightly to

15      <%= f.input :author, :as => :check_boxes %>

to make check-boxes out of the list-box.... but... ewww.... look at this:
left to right checkbox display

13) something seems slightly wrong... the left to right presentation of the options is known to trouble simple_form greenhorns every now and then, but actually its an easy to fix issue

and on top of that little format issue, you might also want to see the Users age behind his name in braces, like 'Tom (25)'

... so lets do 3 quick fixes

a) uncomment and set 2 options in config/initializers/simple_form.rb in order to wrap each checkbox with a div and to place the set of checkboxes inside a fieldset

  # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
  config.collection_wrapper_tag = :fieldset

  # You can wrap each item in a collection of radio/check boxes with a tag, defaulting to none.
  config.item_wrapper_tag = :div

b) modify our simple_form.css stylesheet a little, as in add:

fieldset { border: 0; }

... unless you'd prefer a big ugly border surrounding the fieldset

c) create the method 'to_label' in our user-model, as 'to_label' is by default the first method simple_form looks for in order to get a String-representation to display an object. By a strange incident our model User has a column called 'name'. As name also is a method simple_form looks for in a model we were lucky this app has worked so far. If we had called the name column forename instead, Rails would have listed not the user names but the default-ruby-object representations (e. g. <#User:521369846>). Guess we were lucky ;-)

app/models/user.rb

class User < ActiveRecord::Base
  has_and_belongs_to_many :users

  def to_label
    "#{name} (#{age})"
  end

end

and the edit-form gets a nice look...
nice and cozy edit view

14) Now only the show view needs to display the book owners... thats not too hard either, just open the show-view

app/views/books/show.html.erb

and add lines 13-16 to display the bookowners:

01    <p id="notice"><%= notice %></p>
02    
03    <p>
04      <b>Title:</b>
05      <%= @book.title %>
06    </p>
07    
08    <p>
09      <b>Author:</b>
10      <%= @book.author %>
11    </p>
12    
13    <p>
14      <b>Who owns a copy?</b>
15      <%= @book.users.map {|x| x.to_label}.join ', ' %>
16    </p>
17    
18    <%= link_to 'Edit', edit_book_path(@book) %> |
19    <%= link_to 'Back', books_path %>

and last but not least ... the show view
Who owns a book?

15) Well, so much for a quick tutorial to habtm or in words has_and_belongs_to_many associations in rails. I have put my test-app I created while writing this online at
https://1drv.ms/u/s!Alpu50oGtUZq7AiJkL08QqBiMAjb

ζ澈沫 2024-11-01 10:23:38

观看 Ryan Bate 关于令牌字段的教程:

http://railscasts.com/episodes/258-token-fields

这是在 Rails 中构建多对多关系的简单方法

Watch Ryan Bate's tutorial on Token Fields:

http://railscasts.com/episodes/258-token-fields

It's a simple way to scaffold a many to many relationship in rails

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文