2016-06-17 3 views
0

Что я хотел бы сделать, так это сохранить shop_id в модели Item.Rails: Как сохранить родительское значение ассоциации

Мои модели следующие:

модели

shop.rb

class Shop < ActiveRecord::Base 
    belongs_to :order 
    has_many :items 
    has_many :categories 
end 

item.rb

class Item < ActiveRecord::Base 
    belongs_to :shop 
    has_many :categories 
end 

схема

ActiveRecord::Schema.define(version: 20160615060137) do 

... 

    create_table "shops", force: :cascade do |t| 
    t.string "name" 
    t.integer "order_id" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    end 

    create_table "items", force: :cascade do |t| 
    t.string "name" 
    t.integer "shop_id" 
    t.datetime "created_at", null: false 
    t.datetime "updated_at", null: false 
    end 

... 

end 

Как я могу создать контроллер new и create для сохранения shop_id в items? Я могу получить такой параметр, как Shop.find_by(id: params[:shop_id])

Было бы полезно, если бы вы могли дать мне какое-либо предложение.

UPDATE

Когда я пытаюсь @ ответ Саада, в NoMethodError был показан ниже.

NoMethodError (undefined method `to_key' for #<Item::ActiveRecord_Associations_CollectionProxy:0x007f901e079a30> 
Did you mean? to_query 
       to_ary): 
    app/views/items/new.html.erb:4:in `_app_views_items_new_html_erb__3601549985910054210_70128472136980' 



NoMethodError (undefined method `to_key' for #<Item::ActiveRecord_Associations_CollectionProxy:0x007f901e079a30> 
Did you mean? to_query 
       to_ary): 
    app/views/items/new.html.erb:4:in `_app_views_items_new_html_erb__3601549985910054210_70128472136980' 

линии new.html.erb: 4 выглядит следующим образом (я не использую частичного _form.html.erb до сих пор);

<%= form_for(@item, url: shop_items_path, method: :post) do |f| %> 

UPDATE2

routes.rb, как показано ниже.

routes.rb

Rails.application.routes.draw do 

    ... 

    resources :items,    only: [:new, :create, :edit, :update] 

    resources :shops do 
    resources :items 
    end 

    ... 

ответ

1

Улучшение previuos кода и предполагая, что вы магазины и контроллер детали вложенные:

class ItemsController < ApplicationController 
    before_action :load_shop 

    def index 
    @items = @shop.items 
    end 

    def new 
    @item = Item.new 
    @item.shop = @shop 
    end 

    def create 
    @item = Item.new(item_params) 
    respond_to do |format| 
     if @item.save 
     format.html { redirect_to shop_item_path(@shop, @item), notice: 'Item was successfully created.' } 
     format.json { render :show, status: :created, location: @item } 
     else 
     format.html { render :new } 
     format.json { render json: @item.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    private 
    def load_shop 
    @shop = Shop.find(params[:shop_id]) 
    end 

    def item_params 
    params.require(:item).permit(:name, :shop_id) 
    end 
end 


<%= form_for([@shop, @item]) do |f| %> 

    <div class="field"> 
     <%= f.label :name %><br> 
     <%= f.text_field :name %> 
    </div> 
    <%= f.hidden_field :shop_id%> 
    <div class="actions"> 
     <%= f.submit %> 
    </div> 
<% end %> 
+0

Спасибо за ваш ответ @DennisCastro. При попытке вашего кода отобразилась следующая ошибка. 'ActiveRecord :: RecordNotFound (не удалось найти Shop без ID): app/controllers/item_controller.rb: 38: in 'load_shop''. Было бы хорошо, если бы вы могли дать мне какое-либо предложение. – SamuraiBlue

+0

Как я сказал.Я думаю, что вы используете вложенные контроллеры, вставьте свой маршрут – DennisCastro

+0

Благодарим вас за комментарий @DennisCastro. Я добавил 'routes.rb' в нижней части моего вопроса. – SamuraiBlue

0

items_controller.rb

class ItemsController < ApplicationController 
    before_action :set_item, only: [:show, :edit, :update, :destroy] 

    def index 
    @shop = Shop.find(params[:shop_id]) 
    @items = @shop.items 
    end 

    def new 
    @shop = Shop.find(params[:shop_id]) 
    @item = Item.new 
    end 
    def create 
    @shop = Shop.find(params[:shop_id]) 
    @item = Item.new(item_params) 

    respond_to do |format| 
     if @item.save 
     format.html { redirect_to shop_item_path(@shop, @item), notice: 'Item was successfully created.' } 
     format.json { render :show, status: :created, location: @item } 
     else 
     format.html { render :new } 
     format.json { render json: @item.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    private 
    # Use callbacks to share common setup or constraints between actions. 
    def set_item 
     @shop = Shop.find params[:shop_id] 
     @item = @shop.items.find(params[:id]) 
    end 

    # Never trust parameters from the scary internet, only allow the white list through. 
    def item_params 
     params.require(:item).permit(:name, :shop_id) 
    end 
end 

_form.html.erb

<%= form_for(@item, url: shop_items_path, method: :post) do |f| %> 
    <% if @item.errors.any? %> 
    <div id="error_explanation"> 
     <h2><%= pluralize(@item.errors.count, "error") %> prohibited this item from being saved:</h2> 

     <ul> 
     <% @item.errors.full_messages.each do |message| %> 
     <li><%= message %></li> 
     <% end %> 
     </ul> 
    </div> 
    <% end %> 

    <div class="field"> 
    <%= f.label :name %><br> 
    <%= f.text_field :name %> 
    </div> 
    <%= f.hidden_field :shop_id, value: @shop.id %> 
    <div class="actions"> 
    <%= f.submit %> 
    </div> 
<% end %> 

index.html.erb

<p id="notice"><%= notice %></p> 

<p> 
    <strong>Name:</strong> 
    <%= @item.name %> 
</p> 

<p> 
    <strong>Shop:</strong> 
    <%= @item.shop %> 
</p> 

<%= link_to 'Edit', edit_shop_item_path(@shop, @item) %> | 
<%= link_to 'Back', shop_items_path(@shop) %> 
+0

Спасибо за ваш ответ, @Sadd. Я попытался, но это не сработает. Было бы хорошо, если бы вы могли дать мне какое-либо предложение. – SamuraiBlue

+0

вы можете поделиться своим кодом на github @SamuraiBlue – Saad

Смежные вопросы