ruby-on-rails 将Carrierwave作为json存储到现有的jsonb列中

e5njpo68  于 2023-05-19  发布在  Ruby
关注(0)|答案(1)|浏览(126)

我不确定这是否可能使用Carrierwave,我仍然在学习Ruby和Rails,所以请原谅我。
我有一个简单的表格来记录观察结果。每个观察都有可以针对它记录的数据,我将这些数据存储在观察中的JSONB列中(我最终将针对一个观察存储多组数据)。我希望能够通过Carrierwave上传图像,并将其与JSONB列中的数据一起存储,而不是将其保存到自己的列中。因此,我保存的此列数据将是这样的,例如...

{  
   "ph":"",
   "ecoli":"",
   "nitri":"Less than 0.5",
   "oxygen":"",
   "clarity":"bottom visible",
   "nitrates":"Less than 0.5",
   "conditions":[  
      "Wildlife Death",
      "Shoreline Alterations",
      "Water Quality"
   ],
   "observed_on":"2015-06-21T04:45",
   "invasive_species":[  
      "Phragmites",
      "Loosestrife",
      "Dog-Strangling Vine"
   ],
   "phosphates_threshold":"less than 0.2",
   "image":[  
      "url": "the/url",
      "thumbnail: "the/thumbnail/url",
      "medium":"the/thumbnail/url"
      .....
   ]
}

部分配套代码供参考…

  • 观察.rb*
class Observation < ActiveRecord::Base
  belongs_to :user
  has_many :comments
  serialize :observation_data, HashSerializer
  store_accessor :observation_data
end
  • observation_data.rb -无表模型 *
class ObservationData < ActiveRecord::Base
  belongs_to :observation
  mount_uploader :image, ImageUploader
end
  • _form.html.erb*
<%= form_for @observation do |f| -%>
  ...Other form items
  <fieldset>
    <legend>Observation data</legend>
    <%= render "observation_data", :f => f %>
  </fieldset>
  <div class="actions">
    <%= f.submit "Submit", class: "button" %>
  </div>
<% end %>
  • _observation_data.html.erb*
<%= f.fields_for :observation_data, OpenStruct.new(@observation.observation_data)  do |o| %>
  ...Other form items
  <div class="field">
    <%= o.label :image, "Upload an image" %>
    <%= o.file_field :image %>
  </div>
  ...Other form items
<% end %>
  • observations_controller.rb*
class ObservationsController < ApplicationController

  before_action :set_observation, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user!

  def index
    @observations = Observation.all
    @user = current_user.id
  end

  def show
    @observations = Observation.find_by(id: params[:id])
    @observation_data = @observation.observation_data
    @comments = @observation.comments.all
    @comment = @observation.comments.build
    @user = User.find_by(id: @observation.user_id)
  end

  def new
    @observation = Observation.new 
  end

  def edit

  end

  def create
    @observation = Observation.new(observation_params)
    @observation.user_id = current_user.id
    respond_to do |format|
      if @observation.save
        format.html { redirect_to @observation, notice: 'Observation was successfully created.' }
        format.json { render action: 'show', status: :created, location: @idea }
      else
        format.html { render action: 'new' }
        format.json { render json: @observation.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @observation.update(observation_params)
        format.html { redirect_to @observation, notice: 'Observation was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @observation.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @observation.destroy
    respond_to do |format|
      format.html { redirect_to root_url }
      format.json { head :no_content }
    end
  end

  private

    def set_observation
      @observation = Observation.find(params[:id])
    end

    def observation_params
      params.require(:observation).permit(:user_id, :lat, :lng, :name, :description, :comment, observation_data: [:observed_on, :image, :ph, :oxygen, :ecoli, :phosphates_threshold, :clarity, :nitri, :nitrates, wildlife: [], conditions: [], invasive_species: []])
    end

end

对我来说,问题是mount_uploader :image, ImageUploader总是在寻找:image列,我如何将载波响应this与另一列中的JSON合并?这可能吗

tzdcorbm

tzdcorbm1#

是的,你可以做到这一点,所以这就是我如何为store选项创建一个 Package 器,并根据他们的建议进行了一些巧妙的覆盖。在您的情况下,可以简化为JSON对象内的主图像键,并与其他数据作为补充。因为这一个的目的是更开放和所有的图像。
这是一个例子:

迁移

# Set the column accordingly to your need like observation_data
  t.jsonb :images

型号

class Campaign < ApplicationRecord
  AVAILABLE_IMAGES = %i[
    home_desktop_img
    home_mobile_img
    srp_desktop_img
    srp_mobile_img
    money_desktop_img
    money_mobile_img
  ].freeze

  store :images, accessors: AVAILABLE_IMAGES, coder: JSON

  AVAILABLE_IMAGES.each do |image_type|
    # General image method change based on store
    define_method(:"#{image_type}_will_change!") { images_will_change! }
    mount_uploader image_type, CampaignImageUploader
  end

  def read_uploader(column)
    column_sym = column.to_sym
    if AVAILABLE_IMAGES.include? column_sym
      read_store_attribute(:images, column_sym)
    else
      super(column)
    end
  end

  def write_uploader(column, identifier)
    column_sym = column.to_sym
    if AVAILABLE_IMAGES.include? column_sym
      write_store_attribute(:images, column_sym, identifier)
    else
      super(column, identifier)
    end
  end
end

相关问题