2013-03-10 64 views
3

我已阅读了许多其他主题(1,2,3 ...),但没有真正解决我的问题。通过关联更新has_many中的模型,使用另外两个模型

这里是我的模型。

​​

正如你所看到的,我的加盟模式成员了一个附加属性::url

在我帐户表,我存储的在线服务,如GitHub上,堆栈溢出,推特,脸谱,LinkedIn的名字。我总共有。这是一个固定数量的帐户,我不倾向于经常更新。

在我用户形式,我想创建此:

User nested form

在这些领域应在成员只有表提交的输入值,使用3个值:

  • url(中文本字段中输入值)
  • user_id(当前用户表单的ID)
  • account_id(相关帐户的ID,例如, LinkedIn是'5')

我试过3个选项。他们都工作,但只是部分。

选项#1

<% for account in @accounts %> 
    <%= f.fields_for :memberships do |m| %> 
    <div class="field"> 
     <%= m.label account.name %><br> 
     <%= m.text_field :url %> 
    </div> 
    <% end %> 
<% end %> 

我想有文本字段,一个为每个帐户。所以我通过我的账户循环,并创建一个与我的会员模型相关的url字段。

这表明我的第一次领域正确,但下一次它会显示领域:

Loop issue

选项#2

<% @accounts.each do |account| %> 
    <p> 
    <%= label_tag(account.name) %><br> 
    <%= text_field_tag("user[memberships_attributes][][url]") %> 
    <%= hidden_field_tag("user[memberships_attributes][][account_id]", account.id) %> 
    <%= hidden_field_tag("user[memberships_attributes][][user_id]", @user.id) %> 
    </p> 
<% end %> 

我m试图手动在我的会员资格表的每一列中输入3个值。

它的工作原理,但:

  • 显示帐户和用户ID似乎并不十分安全(无?)
  • 将每次重置的域修改我的用户
  • 将复制值在每个提交

选项#3(最好的一项)

<%= f.fields_for :memberships do |m| %> 
    <div class="field"> 
    <%= m.label m.object.account.name %><br> 
    <%= m.text_field :url %> 
    </div> 
<% end %> 

我创建在我的用户窗体中嵌套窗体,为我的成员模型。

它的工作原理几乎完美:

  • 正好9个字段,每个占
  • 没有重复

,它只能如果我的成员表已填充! (例如使用选项#2)。

所以我尝试使用UsersController建设一些实例:

if (@user.memberships.empty?) 
    @user.memberships.build 
end 

但我仍然得到这个错误我m.label m.object.account.name线。

undefined method `name' for nil:NilClass 

无论如何,我可能在这里通过模型失去了关于has_many的一些东西。我设法创建了has_and_belongs_to_many关联,但在这里,我想通过第一个模型(用户)使用关于第三个模型(Account)的信息来处理该连接模型(Membership)。

我很感谢您的帮助。谢谢。

+0

为什么你在账户模型的has_many用户?我帐户,例如[email protected]属于许多用户? – Zippie 2013-03-10 14:19:25

+0

@ Zippie不,这将是'帐户* GitHub *有很多用户'。我并未完全使用用户和帐户之间的直接关系,而仅仅是连接模型。 – jgthms 2013-03-10 14:32:14

回答

2

,通过每个帐户提取成员资格列表中用于特定用户的

# controller 
# no need to make this an instance variable since you're using fields_for in the view 
# and we're building additional memberships later 
memberships = @user.memberships 

然后循环并建立一个成员资格,如果用户没有成员资格一个帐户。

# still in the controller 
Account.find_each do |account| 
    unless memberships.detect { |m| m.account_id == account.id } 
    @user.memberships.build account_id: account.id 
    end 
end 

那么在你看来,你改变什么:)

+0

谢谢!我最终使用了Harish的答案和你的答案。 – jgthms 2013-03-15 11:49:44

2

我会使用下面的数据设计方法。系统中的所有用户应该拥有所有可能帐户的 memebership条目。活动配置将具有url字段的值。

User 
    has_many :memberships 
    has_many :accounts, :through => :memberships 
    has_many :active_accounts, :through => :memberships, 
      :source => :account, :conditions => "memberships.url IS NOT NULL" 

    accepts_nested_attributes_for :memberships 
end 

现在

curent_user.active_accounts # will return the accounts with configuration 
curent_user.accounts # will return all possible accounts 

添加before_filter初始化所有用户可以拥有成员。

class UsersController 

    before_filter :initialize_memberships, :only => [:new, :edit] 

private 

    def initialize_memberships 
    accounts = if @user.accounts.present? 
     Account.where("id NOT IN (?)", @user.account_ids) 
    else 
     Account.scoped 
    end   
    accounts.each do |account| 
     @user.memberships.build(:account_id => account.id) 
    end 
    end 
end  

在这种情况下,你需要的new行动前初始化memeberships和所有的成员应该 可以(不url连的)保存在create行动。

您的编辑动作不需要执行任何额外的数据按摩。

注:

我建议这种方法,因为它使形式/数据管理直截了当。如果与Account关联的数量很少,则只应使用 。

在控制器
+0

有几个问题:1)这是否也会使用正确的user_id填充@ account.memberships? 2)如果他要存储额外的参数:url,这会工作:@ user.memberships.build(:account_id => account.id,:url =>'someURL')?谢谢:-) – nicohvi 2013-03-14 10:41:29

+0

更新了答案看看。 – 2013-03-14 17:58:33

+0

是否@ user.memberships.empty?如果即使一个成员资格出现在我的会员资格表(针对当前用户)中,也会返回false?所以,如果我要添加新的账户(比如Reddit或黑客新闻),他们不会建立,他们会吗? – jgthms 2013-03-15 02:51:41

相关问题