2015-08-17 5 views
18

फीनिक्स ढांचे में संघों और नेस्टेड रूपों को संभालने का तरीका क्या है? नेस्टेड विशेषताओं के साथ कोई फॉर्म कैसे बनाएगा? इसे नियंत्रक और मॉडल में कैसे संभाला जाएगा?फीनिक्स ढांचे में एसोसिएशन और नेस्टेड रूपों को कैसे संभालें?

उत्तर

15

1-1 स्थिति को संभालने का एक सरल उदाहरण है।

कल्पना कीजिए कि हम एक Car और एक Engine मॉडल और स्पष्ट रूप से एक Car has_one Engine है। तो वहाँ कार के मॉडल

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

    schema "cars" do 
    field :name, :string    

    has_one :engine, MyApp.Engine 

    timestamps 
    end 

    def changeset(model, params \\ :empty) do 
    model 
    |> cast(params, ~w(name), ~w()) 
    |> validate_length(:name, min: 5, message: "No way it's that short")  
    end 

end 

और इंजन मॉडल फार्म के लिए

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

    schema "engines" do 
    field :type, :string    

    belongs_to :car, MyApp.Car 

    timestamps 
    end 

    def changeset(model, params \\ :empty) do 
    model 
    |> cast(params, ~w(type), ~w()) 
    |> validate_length(:type, max: 10, message: "No way it's that long")  
    end 

end 

सरल टेम्पलेट के लिए कोड है ->

<%= form_for @changeset, cars_path(@conn, :create), fn c -> %> 

    <%= text_input c, :name %> 

    <%= inputs_for c, :engine, fn e -> %> 

    <%= text_input e, :type %> 

    <% end %> 

    <button name="button" type="submit">Create</button> 

<% end %> 

और नियंत्रक ->

defmodule MyApp.CarController do 
    use MyApp.Web, :controller 
    alias MyApp.Car 
    alias MyApp.Engine 

    plug :scrub_params, "car" when action in [:create] 

    def new(conn, _params) do  
    changeset = Car.changeset(%Car{engine: %Engine{}})  
    render conn, "new.html", changeset: changeset 
    end 

    def create(conn, %{"car" => car_params}) do  
    engine_changeset = Engine.changeset(%Engine{}, car_params["engine"]) 
    car_changeset = Car.changeset(%Car{engine: engine_changeset}, car_params) 
    if car_changeset.valid? do 
     Repo.transaction fn -> 
     car = Repo.insert!(car_changeset) 
     engine = Ecto.Model.build(car, :engine) 
     Repo.insert!(engine) 
     end 
     redirect conn, to: main_page_path(conn, :index) 
    else 
     render conn, "new.html", changeset: car_changeset 
    end 
    end  

end 

और एक दिलचस्प ब्लॉग पोस्ट पर विषय जो कुछ चीजों को भी स्पष्ट कर सकता है ->here

+0

के बाद से मैं संपत्ति परीक्षण करने का मौका नहीं था उदाहरण के कुछ मामूली त्रुटियों हो सकता है या नहीं एक बिल्कुल सही ढंग से लिखा जा के बाद से मैं इस ढांचे को नया हूँ, लेकिन मैं अपने आप को उम्मीद है कि इससे किसी चीज को खुद के लिए बाहर निकालने में थोड़ी देर बचाने में मदद मिलेगी। बस कुछ प्रश्नों के उत्तर खोजने का प्रयास करना आसान है क्योंकि विषय – JustMichael

+0

पर बहुत सारी जानकारी नहीं है, इस समाधान के साथ समस्या अगर उदाहरण के लिए 'कार' के नाम के लिए विशिष्टता की तरह बाधा होगी, तो लेनदेन विफल हो जाएगा और फॉर्म के लिए कोई त्रुटि नहीं दी जाएगी। मैं इसमें फंस गया हूं: http://stackoverflow.com/a/38035026?noredirect=1 – masylum

+0

यहां एक परीक्षण दिखाया गया है कि आप ecto 2 में नेस्टेड डालने कैसे करेंगे, https://github.com/elixir-ecto/ ecto/blob/6f1971f4120b84e1a441792feb77ba451c4fc783/integration_test/case/repo.exs # L720 – opsb

2

has_many संबंध के साथ एक ही समस्या में भाग लें। दुर्भाग्य से, एक Car कई Engines नहीं हो सकता, इसलिए मैं कई TodoItems

TodoList मॉडल के साथ इस blogpost में एक ही उदाहरण लेते हैं, एक TodoList की,:

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

    schema "todo_lists" do 
    field :title, :string    

    has_many :todo_items, MyApp.TodoItem 

    timestamps 
    end 

    def changeset(model, params \\ :{}) do 
    model 
    |> cast(params, [:title]) 
    |> cast_assoc(:todo_items) 
    end 
end 

TodoItem मॉडल:

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

    schema "todo_items" do 
    field :body, :string 

    belongs_to :todo_list, MyApp.TodoList 

    timestamps 
    end 

    def changeset(model, params \\ :{}) do 
    model 
    |> cast(params, [:body]) 
    end 
end 

यहां फॉर्म बनाने के लिए TodoList है। चीजों को सरल रखने के लिए बस अभी एक आइटम जोड़ें।

<%= form_for @changeset, todo_lists_path(@conn, :create), fn f -> %>  
    <%= text_input f, :title %> 
    <%= inputs_for f, :todo_items, fn i -> %> 
    <%= text_input i, :body %> 
    <% end %> 
    <button name="button" type="submit">Create</button> 
<% end %> 

यह TodoListController जैसा दिखता है। create विधि सही पाने के लिए सबसे कठिन था। मुझे यह काम करने का एक तरीका खोजने के लिए एक्टो टेस्ट में खोदना पड़ा। Link

defmodule MyApp.TodoListController do 
    use MyApp.Web, :controller 

    alias MyApp.TodoList 
    alias MyApp.TodoItem 

    def new(conn, _params) do 
    todo_item = TodoItem.changeset(%TodoItem{}) 
    changeset = TodoList.changeset(%TodoList{todo_items: [todo_item]}) 

    render conn, "new.html", changeset: changeset 
    end 

    def create(conn, %{"todo_list" => todo_list_params}) do 
    todo_item_changeset = 
     TodoItem.changeset(%TodoItem{}, todo_item["todo_items"]["0"]) 
    changeset = 
     TodoList.changeset(%TodoList{}, %{title: todo_list_params["title"]}) 
     |> Ecto.Changeset.put_assoc(:todo_items, [todo_item_changeset]) 

    case Repo.insert(changeset) do 
     {:ok, company} -> 
     conn 
     |> put_flash(:info, "TodoList created!") 
     |> redirect(to: page_path(conn, :index)) 
     {:error, changeset} -> 
     conn 
     |> render "new.html", changeset: changeset 
    end 
    end 
end 

http://pranavsingh.co/storing-nested-associations-with-phoenix-forms/

+2

कोई भी विचार है कि एकाधिक आइटम कैसे जोड़ना है, गतिशील रूप से उन्हें फ़ॉर्म में जोड़ना/निकालना? –

संबंधित मुद्दे