开发者

Rails 3: alias_method_chain to set specific attribute first

开发者 https://www.devze.com 2023-03-20 16:30 出处:网络
When user\'s create a post I\'d like to set the user_id attribute first. I\'m trying to do this using alias_method_chain on the arrtibutes method. But I\'m not sure if this is right as the problem I t

When user's create a post I'd like to set the user_id attribute first. I'm trying to do this using alias_method_chain on the arrtibutes method. But I'm not sure if this is right as the problem I thought this would fix is still occurring. Is this correct?

Edit:

When my users create a post they assign 'artist(s)' to belong to each post, using a virtual attribute called 'artist_tokens'. I store the relationships in an artist model and a joined table of artist_ids and post_ids called artisanships.

I'd like to to also store the user_id of whomever creat开发者_运维知识库ed the artist that belongs to their post (and I want it inside the artist model itself), so I have a user_id column on the artist model.

The problem is when I create the artist for each post and try to insert the user_id of the post creator, the user_id keeps showing as NULL. Which is highly likely because the post's user_id attribute hasn't been set yet.

I figured to get around this I needed to set the user_id attribute of the post first, then let the rest of the attributes be set as they normally are. This is where I found alias_method_chain.

post.rb

 attr_reader :artist_tokens

  def artist_tokens=(ids)
    ids.gsub!(/CREATE_(.+?)_END/) do
      Artist.create!(:name => $1, :user_id => self.user_id).id
    end
    self.artist_ids = ids.split(",")
  end


    def attributes_with_user_id_first=(attributes = {})
      if attributes.include?(:user_id)
        self.user_id = attributes.delete(:user_id)
      end
      self.attributes_without_user_id_first = attributes
    end
    alias_method_chain :attributes=, :user_id_first

EDIT:

class ArtistsController < ApplicationController

  def index
    @artists = Artist.where("name like ?", "%#{params[:q]}%")
    results = @artists.map(&:attributes)
    results << {:name => "Add: #{params[:q]}", :id => "CREATE_#{params[:q]}_END"}

    respond_to do |format|
      format.html
      format.json { render :json => results }
    end
  end


In your controller, why not just do this:

def create
  @post = Post.new :user_id => params[:post][:user_id]
  @post.update_attributes params[:post]
  ...
end

But it seems to me that it would be much better to create the artist records after you've done validation on the post rather than when you first assign the attribute.

EDIT

I would change this to a callback like this:

class Post < ActiveRecord::Base
  attr_accessor :author_tokens
  def artist_tokens=(tokens)
    @artist_tokens = tokens.split(',')
  end

  after_save :create_artists
  def create_artists
    @artist_tokens.each do |token|
      ...
    end
  end
end
0

精彩评论

暂无评论...
验证码 换一张
取 消