2016-08-10 8 views
5

मैं एक मॉडल एक है कि एक और मॉडल बीफीनिक्स Ecto: विदेशी कुंजी

defmodule MyApp.ModelA do 
    use MyApp.Web, :model 

    schema "model_a" do 
    field :type, :string, null: false 
    field :data, :string, null: false 
    belongs_to :model_b, MyApp.ModelB 
    timestamps() 
    end 

    @required_fields ~w(type data) 
    @optional_fields ~w() 

    @doc """ 
    Builds a changeset based on the `struct` and `params`. 
    """ 
    def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, @required_fields, @optional_fields) 
    |> assoc_constraint(:model_b) 
    end 
end 

के लिए एक विदेशी कुंजी और मॉडल बी शामिल डालने हूँ डाला जा रहा है नहीं:

defmodule MyApp.ModelB do 
    use MyApp.Web, :model 

    schema "model_b" do 
    field :username, :string 
    field :pass, :string 
    has_many :model_a, MyApp.ModelA 
    timestamps() 
    end 

    @required_fields ~w(username pass) 
    @optional_fields ~w() 

    @doc """ 
    Builds a changeset based on the `struct` and `params`. 
    """ 
    def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, @required_fields, @optional_fields) 
    |> cast_assoc(:model_a) 
    |> validate_required([]) 
    end 
end 

मॉडल बी मौजूद है, क्योंकि मैं इसे Repo.all (ModelB) के माध्यम से प्राप्त कर सकता हूं।

मॉडल एक परिवर्तन सफलतापूर्वक सत्यापित किया गया है, और जब मैं मॉडल ए चेंजसेट प्रिंट प्रिंट करता हूं तो मैं model_b_id मान देख सकता हूं।

लेकिन जब डाला गया, संदर्भ सम्मिलित नहीं किया गया है। हालांकि मैं इसे मॉडल ए के परिवर्तन को प्रिंट करते समय देख सकता हूं, MySQL लॉग में, यह फ़ील्ड पूरी तरह गायब है, INSERT क्वेरी में नहीं है।

मैंने थोड़ा सा खेला है, और यदि मैं इस संदर्भ फ़ील्ड को MySQL तालिका में शून्य नहीं करने के लिए मजबूर करता हूं, तो मुझे Repo.insert (...) प्रतिक्रिया के रूप में डालने पर इस विदेशी कुंजी फ़ील्ड के लिए {"does not exist", []} मिलता है हालांकि, मॉडल बी डेटाबेस में मौजूद है।

+0

परिवर्तनसेट सत्यापन विदेशी कुंजी सत्यापन की जांच नहीं करता है, इसलिए आपको " वास्तव में डालने का प्रयास करने से पहले त्रुटि नहीं है "त्रुटि। क्या आप मॉडलों की स्कीमा और आपके द्वारा चलाए गए कोड और एसक्यूएल लॉग पोस्ट कर सकते हैं? – Dogbert

+0

सोरीरी, शायद मैंने खुद को समझाया नहीं। मुझे Repo.insert (...) की प्रतिक्रिया के रूप में "अस्तित्व में नहीं है" मिलता है। Changeset सत्यापन वास्तव में हमेशा इस मामले के लिए ठीक काम करता है। – David

+0

क्या आप पूरी तरह से सुनिश्चित हैं कि आप परिवर्तन में 'model_b_id' देखते हैं? आपके द्वारा पोस्ट किए गए कोड के अनुसार आपका '@ वैकल्पिक_फील्ड' खाली है। क्या आप 'model_b_id' को 'वैकल्पिक_फील्ड' में जोड़ने का प्रयास कर सकते हैं? – Dogbert

उत्तर

0

मुझे नहीं लगता कि Ecto आप के लिए struct बंद आईडी क्षेत्र खींचती है - मैं कुछ इस तरह कर रहा हूँ:

defmodule MyApp.ModelA do 
    use MyApp.Web, :model 

    schema "model_a" do 
    field :type, :string, null: false 
    field :data, :string, null: false 
    belongs_to :model_b, MyApp.ModelB 
    timestamps() 
    end 

    @required_fields ~w(type data model_b_id) 
    @optional_fields ~w() 

    @doc """ 
    Method head to define what's coming. 
    """ 
  def changeset(model, params \\ :empty) 

    @doc """ 
    Catches the case where you're passing in a model_b struct instead of an integer. 
    Just makes a recursive call with the correct type. 
    """ 
  def changeset(model, %{model_b_id: nil, agency: %MyApp.ModelB{} = model_b} = params) do 
    changeset(model, %{params | model_b_id: model_b.id}) 
  end 

    @doc """ 
    I normally use assoc_constraint on the table index itself like so 
    """ 
    def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, @required_fields, @optional_fields) 
    |> assoc_constraint(:model_b, name: :model_as_model_b_id_fkey) 
    end 
end 
0

मैं परम इस सवाल का एक जवाब में दिलचस्पी थी।

मैं इस पंक्ति को बनाया गया था, मुझे सही स्थिति में 7 घंटे खो दिया था, क्यों ओह क्यों परिवर्तन नहीं है मुझे संदर्भ संग्रह करने की अनुमति दे रहा है? "

मैंने सोचा कि मैं पर उसी निराशा के साथ किसी के लिए एक सुझाव छोड़ दूंगा, अपने डेटाबेस माइग्रेशन संदर्भ देखें।

मुझे यकीन था कि मैंने उन्हें तीन बार चेक किया था, लेकिन वहां अच्छी रात नींद के बाद दिन स्पष्ट था। मैंने गलत तालिका में संदर्भ संदर्भ दिए थे।

उम्मीद है कि यह किसी को कुछ समय बचाता है।

0

क्या मेरे लिए काम किया निम्नलिखित था:

model_b = Repo.get(MyApp.ModelB, 2) 
model_a_changeset = Ecto.build_assoc(model_b, :model_as, 
    type: "Model type", 
    data: "Model data" 
) 
Repo.insert! model_a_changeset 

कभी कभी

आप (संख्या एक model_b की आईडी उदाहरण है, आप यह पता लगाने के लिए कैसे सही पैरेंट आईडी को पुनः प्राप्त करने के लिए है) निम्नलिखित रूप में परिवर्तन सेट पर विदेशी कुंजी निर्दिष्ट करने की आवश्यकता है:

model_a_changeset = Ecto.build_assoc(model_b, :model_as, 
    type: "Model type", 
    data: "Model data", 
    model_b_id: model_b.id 
) 
संबंधित मुद्दे